<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mohamed</title>
    <description>The latest articles on DEV Community by Mohamed (@moaz06).</description>
    <link>https://dev.to/moaz06</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4016053%2Fe1c13bcb-5f59-4498-9e87-640905fbdca8.png</url>
      <title>DEV Community: Mohamed</title>
      <link>https://dev.to/moaz06</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/moaz06"/>
    <language>en</language>
    <item>
      <title>Why trustworthy medical AI makes uncertainty visible instead of hiding it behind a polished clinical note.</title>
      <dc:creator>Mohamed</dc:creator>
      <pubDate>Sun, 26 Jul 2026 11:51:18 +0000</pubDate>
      <link>https://dev.to/moaz06/why-trustworthy-medical-ai-makes-uncertainty-visible-instead-of-hiding-it-behind-a-polished-46go</link>
      <guid>https://dev.to/moaz06/why-trustworthy-medical-ai-makes-uncertainty-visible-instead-of-hiding-it-behind-a-polished-46go</guid>
      <description>&lt;p&gt;A doctor mentions a medication during a consult. The AI writes a different medication name in the clinical note.&lt;/p&gt;

&lt;p&gt;It is still a real medicine. The spelling looks correct. The note is well formatted. Nothing looks obviously broken.&lt;/p&gt;

&lt;p&gt;That is what makes the mistake dangerous.&lt;/p&gt;

&lt;p&gt;When people talk about AI errors, they often imagine something absurd: a made-up diagnosis, nonsense text, or an answer that is visibly wrong. Those failures are easy to catch. The harder failures are plausible enough to pass through a normal workflow without anyone stopping to question them.&lt;/p&gt;

&lt;p&gt;In a medical record, “looks right” is not enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  A useful note is not automatically a trustworthy note
&lt;/h2&gt;

&lt;p&gt;Medical AI scribes can save clinicians a great deal of time. They turn a recorded consult into a structured note, so the clinician does not have to type everything from scratch.&lt;/p&gt;

&lt;p&gt;But the system is working from spoken language. People talk quickly, use abbreviations, interrupt each other, and mention words that sound alike. An AI can misunderstand a medicine, make a weak connection between two facts, or write a note field with more certainty than the conversation supports.&lt;/p&gt;

&lt;p&gt;The problem is not that AI should never help write a note. The problem is what happens when the system is unsure.&lt;/p&gt;

&lt;p&gt;If uncertainty stays hidden, the clinician receives a polished answer that looks ready to accept. If uncertainty is visible, the clinician can make the decision that matters.&lt;/p&gt;

&lt;p&gt;That was the safety goal behind my work on a medical AI scribe: make the system useful without letting a believable mistake quietly become part of the record.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make uncertainty visible
&lt;/h2&gt;

&lt;p&gt;A warning at the bottom of a page is not enough. It is too easy to miss, especially when the rest of the output looks clean.&lt;/p&gt;

&lt;p&gt;Instead, every medication the system recognises should show a clear status. That includes medication names that appear to be exact matches. A name that looks correct can still have been misunderstood in context.&lt;/p&gt;

&lt;p&gt;The reviewer can immediately see which terms need attention, choose a suggested correction, or enter the right name themselves. The system does not ask them to investigate a vague warning. It gives them a clear decision and a quick way to act on it.&lt;/p&gt;

&lt;p&gt;The important change is simple: uncertainty becomes part of the workflow, rather than something hidden behind a successful-looking note.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do not let AI mark its own homework
&lt;/h2&gt;

&lt;p&gt;It is tempting to ask an AI whether its own answer is correct. That may produce a better guess, but it does not create a reliable check.&lt;/p&gt;

&lt;p&gt;For important parts of the note, the system needs fixed rules: checks that give the same answer every time when they see the same evidence.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the medication name match a trusted medical terminology?&lt;/li&gt;
&lt;li&gt;Is a note field supported by facts that were actually extracted from the conversation?&lt;/li&gt;
&lt;li&gt;Is there enough evidence to show this field as a fact, or should it be marked for human review?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the system cannot support a value, it should not write it with confidence. It should leave it empty or flag it clearly for review.&lt;/p&gt;

&lt;p&gt;The AI can still do what it is good at: listening, organising information and proposing a draft. But it should not be allowed to decide that its own uncertain output is safe enough to enter a record.&lt;/p&gt;

&lt;h2&gt;
  
  
  A correction must also be safe
&lt;/h2&gt;

&lt;p&gt;Safety does not only live in the big AI decisions. It also lives in the small actions around them.&lt;/p&gt;

&lt;p&gt;A clinician correcting a medication should never accidentally change other text in the note. An empty confirmation should not overwrite a value that was already there. A review step should make it obvious what will happen before the change is saved.&lt;/p&gt;

&lt;p&gt;These details can sound minor. They are not.&lt;/p&gt;

&lt;p&gt;A medical record is a chain of decisions: what the AI heard, what it proposed, what the system checked, what the clinician reviewed, and what was finally saved. A small unsafe step anywhere in that chain can undermine the rest.&lt;/p&gt;

&lt;p&gt;Good safety work is often less visible than a new AI feature. It is validation, clear statuses, sensible defaults and carefully tested edge cases. But those are the things that keep a helpful tool from becoming quietly unreliable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Human review should mean something
&lt;/h2&gt;

&lt;p&gt;“Human in the loop” is an easy phrase to say. It only matters if the human can genuinely see where the system may be wrong and can correct it without friction.&lt;/p&gt;

&lt;p&gt;A real review step needs to answer three questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is uncertain?&lt;/li&gt;
&lt;li&gt;Why is it uncertain?&lt;/li&gt;
&lt;li&gt;What can I do about it?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the answer is only “please check this,” the reviewer is being asked to do extra work without help. If the system points to the exact medication or note field, explains its status and offers a safe correction path, review becomes a meaningful control.&lt;/p&gt;

&lt;p&gt;The clinician is not there to rubber-stamp the AI. The interface should help them disagree with it when it matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this does not solve
&lt;/h2&gt;

&lt;p&gt;These checks do not make an AI system medically infallible. They cannot decide what a doctor truly intended in every conversation. They do not replace clinical judgement.&lt;/p&gt;

&lt;p&gt;What they can do is more honest: stop the system from hiding uncertainty behind confident language.&lt;/p&gt;

&lt;p&gt;When the evidence is strong, the system can help quickly. When the evidence is weak, the system should say so. And when a decision needs a clinician, the workflow should make that decision visible and easy to take.&lt;/p&gt;

&lt;p&gt;That is what trustworthy AI looks like in production.&lt;/p&gt;

&lt;p&gt;Not an AI that never makes mistakes. A system that makes uncertainty impossible to ignore.&lt;/p&gt;




&lt;p&gt;I’m Mohamed Azahrioui, a backend and AI-safety developer building deterministic, auditable controls for production AI systems.&lt;/p&gt;

&lt;p&gt;This is a software-engineering article, not medical advice.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>healthtech</category>
      <category>softwareengineering</category>
      <category>ux</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Mohamed</dc:creator>
      <pubDate>Fri, 17 Jul 2026 17:42:43 +0000</pubDate>
      <link>https://dev.to/moaz06/-32gm</link>
      <guid>https://dev.to/moaz06/-32gm</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/moaz06/a-200-is-not-a-read-2on" class="crayons-story__hidden-navigation-link"&gt;A 200 Is Not a Read&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/moaz06" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4016053%2Fe1c13bcb-5f59-4498-9e87-640905fbdca8.png" alt="moaz06 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/moaz06" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Mohamed
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Mohamed
                
              
              &lt;div id="story-author-preview-content-4168592" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/moaz06" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4016053%2Fe1c13bcb-5f59-4498-9e87-640905fbdca8.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Mohamed&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/moaz06/a-200-is-not-a-read-2on" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 17&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/moaz06/a-200-is-not-a-read-2on" id="article-link-4168592"&gt;
          A 200 Is Not a Read
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/python"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;python&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/security"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;security&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/moaz06/a-200-is-not-a-read-2on" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/moaz06/a-200-is-not-a-read-2on#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              1&lt;span class="hidden s:inline"&gt;&amp;nbsp;comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            6 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>A 200 Is Not a Read</title>
      <dc:creator>Mohamed</dc:creator>
      <pubDate>Fri, 17 Jul 2026 17:42:25 +0000</pubDate>
      <link>https://dev.to/moaz06/a-200-is-not-a-read-2on</link>
      <guid>https://dev.to/moaz06/a-200-is-not-a-read-2on</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Your AI agent will answer from a page it never actually read, with a straight face, and the transcript won't tell you. An HTTP 200 means the bytes arrived, not that you got the page. FetchGate turns "did we actually read it?" into a deterministic RETRIEVED / FAILED / UNKNOWN verdict, and hard-fails before the model can bluff.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Give an AI agent a web tool and watch what happens when a fetch fails quietly instead of cleanly. The page comes back as an empty JavaScript shell, a Cloudflare "just a moment" screen, or a 403 dressed up as a 200, and the agent does not stop to notice. It answers anyway, from whatever it already had in its weights, and nothing in the transcript tells you it never read the page. What you get is a confident guess wearing the costume of a retrieval.&lt;/p&gt;

&lt;p&gt;I keep coming back to this shape: a tool answers one question with confidence and leaves a second, more important one unanswered. This time the second question is the smallest and the sharpest one I have worked on: did we actually read the page, yes or no?&lt;/p&gt;

&lt;h2&gt;
  
  
  The visible axis: tokens
&lt;/h2&gt;

&lt;p&gt;The popular version of this problem is about cost. A raw article can be tens of thousands of tokens, so people measure it, complain about it, and reach for cleaner extraction and stealth browsers to shrink it. That cost is real, and it is being handled.&lt;/p&gt;

&lt;p&gt;But cost was never the dangerous part. Context windows grew, extraction improved, and the cost problem mostly dissolved. The dangerous part sat underneath it the whole time and never moved: whether the fetch produced a read at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  The invisible axis: whether the fetch happened
&lt;/h2&gt;

&lt;p&gt;The failure itself is simple. A model is handed no content while a question is waiting to be answered, so it fills the gap. That is what models do; it is not misbehavior. The bug is not the model guessing but the harness that lets an empty retrieval reach a final, grounded-sounding answer.&lt;/p&gt;

&lt;p&gt;It shows up in three ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the fetch returns nothing and the model answers from its training weights,&lt;/li&gt;
&lt;li&gt;the fetch returns nothing and the model answers from a stale prior it happens to hold,&lt;/li&gt;
&lt;li&gt;the fetch succeeds, technically, but returns the wrong content (a challenge page, a consent wall, a soft 404), and the model reads that and answers as if it read the article.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What I am building here is not new groundedness work, and I want to be honest about the neighbors. RAG faithfulness checks like RAGAS and TruLens, abstention work on knowing what you don't know, and citation UX like Perplexity's "could not access this source" all live near this problem and earn their keep. But they evaluate whatever text arrived, after the fact; none of them assert that a fetch of the intended resource actually happened. That narrow delta is the whole point: a check at the fetch boundary, upstream of grounding, that hard-fails before the model ever gets to answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The name of the mistake
&lt;/h2&gt;

&lt;p&gt;The mistake is treating an HTTP 200 as evidence. A 200 means the bytes arrived; it says nothing about whether those bytes are the page you asked for or a wall standing in front of it. A JavaScript app returns a 200 whose body is almost all script and almost no readable text. Cloudflare returns a 200 with a full "verify you are human" page. Both pass every naive check, which is why the question cannot be "did the request succeed" but has to be "did we come away with the page".&lt;/p&gt;

&lt;h2&gt;
  
  
  The gate, not the fields
&lt;/h2&gt;

&lt;p&gt;The obvious fix is to hand the model more metadata: the status code, byte counts, a note that the page looked empty. It does not work, because richer fields the model can read are richer fields the model can ignore. The model will wave past a byte count of zero the same way it waves past an empty body. If it gets a vote on whether it read the page, you have handed the decision back to the component you did not trust in the first place.&lt;/p&gt;

&lt;p&gt;So the decision lives outside the model, in the orchestration layer, as a deterministic gate. The gate reads what the fetch runtime measured and returns one of three verdicts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RETRIEVED: we can point to real, sufficient content. The model may answer and cite it.&lt;/li&gt;
&lt;li&gt;FAILED: we can point to a definite reason there is no read, such as a 4xx or 5xx, a timeout, an HTTPS to HTTP downgrade, or an empty body. The agent stops.&lt;/li&gt;
&lt;li&gt;UNKNOWN: we cannot classify it either way, often because the page is a JavaScript app that needs rendering. The agent stops, or renders and checks again.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Three layers feed the verdict, and the strictest of them wins. The transport layer looks at the status and the redirect chain. The extraction layer keeps readable text separate from raw bytes, so that a 17-byte price JSON counts as a read while a 400 KB script shell does not. The third layer, a content-validity fingerprint, watches for the walls. It is a best-effort heuristic that will rot over time, so it is only ever allowed to pull a verdict down to UNKNOWN; it can never manufacture a read, and the only path to a hard FAILED is a transport signal. The gate fails closed or fails labeled; it never fails fluent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the browser earns its weight
&lt;/h2&gt;

&lt;p&gt;For pages that are genuinely empty to a static reader, the gate escalates to a real headless browser, lets the page render, and classifies again. The point is to render, not to evade: a page that is still walled after an honest render stays UNKNOWN and hard-fails. The gate opens a browser tab the way a person would; it does not defeat a control the site put up on purpose.&lt;/p&gt;

&lt;h2&gt;
  
  
  Provenance is a security property
&lt;/h2&gt;

&lt;p&gt;Answer quality is the obvious reason to care, but not the sharpest one. Agents act on what they read, which makes silent fetch failure an attack surface as well as a bug. If I can make your agent's fetch quietly fail, or serve it a decoy, I can steer what it does next. Retrieval suppression, cloaking, and context poisoning are all attacks on an agent that trusts a 200.&lt;/p&gt;

&lt;p&gt;That is why every decision ships with a receipt: the final URL after redirects, the status, raw bytes versus extracted bytes, and a content hash. A receipt is only as strong as what it proves, so it comes with two honest limits. The hash pins down what was read, which makes a later claim re-checkable, but it is not tamper-evidence; a cloaked page hashes cleanly. And provenance is not authenticity: the gate closes the fail-silent-on-empty hole, not the case where a fetch succeeds on wrong content that slips past the fingerprint. It raises the bar from "no evidence" to "evidence that passed the checks". That is worth having, and it is not everything.&lt;/p&gt;

&lt;p&gt;There is a third limit: a read is not an answer. RETRIEVED means enough content arrived, not that it contained the fact you needed. Checking that is groundedness work, and it composes downstream, after the gate has done its one job.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pattern underneath
&lt;/h2&gt;

&lt;p&gt;This is the third time I have built the same shape. ReachGate decides whether a vulnerability is actually reachable in your code before a human touches the finding. TrustGate decides whether an agent may take a risky action given the live state of the data behind it. FetchGate decides whether a page was actually read before the agent answers from it.&lt;/p&gt;

&lt;p&gt;The domains differ, but the idea is the same: let a deterministic engine make the call, let the model only explain it, and ship every decision as proof you can check yourself.&lt;/p&gt;

&lt;p&gt;FetchGate is the smallest of the three, a gate that comes down to nearly one bit: read or not. But the fetch boundary is where an agent's grip on reality is thinnest, and it is the one place the other two do not cover. It is open source and deterministic, runs with no model and no API keys, and ships with a test that tries to sneak a fabricated read past the gate; the forgery gets caught, by design. A 200 is not a read, and an agent that cannot tell the difference will tell you it read a page it never saw, with a straight face, every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"fetchgate[mcp]"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/MoAz06/FetchGate" rel="noopener noreferrer"&gt;FetchGate on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pypi.org/project/fetchgate/" rel="noopener noreferrer"&gt;FetchGate on PyPI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/MoAz06/FetchGate/releases" rel="noopener noreferrer"&gt;One-click Claude Desktop bundle&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is open source and deterministic. If it saves you one silent bad answer, a star on the &lt;a href="https://github.com/MoAz06/FetchGate" rel="noopener noreferrer"&gt;repo&lt;/a&gt; helps others find it.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>security</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
