<?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: Otito Ogene</title>
    <description>The latest articles on DEV Community by Otito Ogene (@otitodev).</description>
    <link>https://dev.to/otitodev</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%2F4037489%2F8a278417-67d9-4784-94b2-2113ad9bcec8.jpg</url>
      <title>DEV Community: Otito Ogene</title>
      <link>https://dev.to/otitodev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/otitodev"/>
    <language>en</language>
    <item>
      <title>One agent, four channels: notes from building on Qwen Cloud</title>
      <dc:creator>Otito Ogene</dc:creator>
      <pubDate>Mon, 20 Jul 2026 19:07:06 +0000</pubDate>
      <link>https://dev.to/otitodev/one-agent-four-channels-notes-from-building-on-qwen-cloud-299</link>
      <guid>https://dev.to/otitodev/one-agent-four-channels-notes-from-building-on-qwen-cloud-299</guid>
      <description>&lt;p&gt;A patient sent us a WhatsApp message at 8:47 PM:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Ive had crushing chest pain for an hour what do I do"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Two things happened in about 400 milliseconds. The agent — a LangGraph state machine running behind FastAPI, hitting &lt;code&gt;qwen3.7-plus&lt;/code&gt; through DashScope's OpenAI-compatible endpoint — classified the intent as &lt;code&gt;escalate&lt;/code&gt;, cut off its own reply generation, and posted a red card to a human-in-the-loop queue at &lt;code&gt;/staff&lt;/code&gt;. The patient got a short "One moment while I get a human on this" acknowledgment. The clinician on-call picked up the card, typed "Please go to the ER now, call us from there," and it landed in the same WhatsApp thread inside a second.&lt;/p&gt;

&lt;p&gt;That's the demo I've spent the last week building for the &lt;a href="https://qwencloud-hackathon.devpost.com/" rel="noopener noreferrer"&gt;Qwen Cloud Hackathon&lt;/a&gt; Track 4. This post is the &lt;em&gt;interesting&lt;/em&gt; bits — not the boilerplate.&lt;/p&gt;

&lt;h2&gt;
  
  
  What MainDesk actually is
&lt;/h2&gt;

&lt;p&gt;A clinic's autonomous front desk that answers on &lt;strong&gt;every channel a patient might use&lt;/strong&gt; — WhatsApp, email, web chat, and voice (a real phone number over Twilio, or a no-download browser call widget) — in English or Mandarin, all day. Books real appointments — Google Calendar integration is built in for real free/busy checks, with a local Postgres scheduler as the fallback for clinics that haven't connected a calendar yet (ours hasn't, in this demo). Escalates to a human dashboard when the model's confidence dips below &lt;code&gt;0.45&lt;/code&gt; or the intent looks medical-urgent.&lt;/p&gt;

&lt;p&gt;The whole thing runs on a &lt;strong&gt;$32/month Alibaba Cloud ECS box&lt;/strong&gt; in Singapore, with TLS via Let's Encrypt at &lt;a href="https://maindesk.otito.site/chat" rel="noopener noreferrer"&gt;maindesk.otito.site&lt;/a&gt;. Try &lt;code&gt;你好，我想预约下周二的检查&lt;/code&gt; in the widget — it works, and it comes back in Mandarin with real appointment slots.&lt;/p&gt;

&lt;p&gt;Code: &lt;a href="https://github.com/Otitodev/Maindesk" rel="noopener noreferrer"&gt;github.com/Otitodev/Maindesk&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, the interesting bits.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Qwen Cloud gotcha that cost me an hour
&lt;/h2&gt;

&lt;p&gt;Every DashScope tutorial on the internet shows the same snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DASHSCOPE_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://dashscope.aliyuncs.com/compatible-mode/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things are wrong for a Qwen Cloud workspace (as opposed to legacy Model Studio):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Endpoint&lt;/strong&gt;: it's &lt;code&gt;dashscope-intl.aliyuncs.com&lt;/code&gt;, not &lt;code&gt;dashscope&lt;/code&gt;. The mainland endpoint returns &lt;code&gt;401 invalid_api_key&lt;/code&gt; on international workspace keys with a confusingly-worded error. Took me 20 minutes to catch the &lt;code&gt;-intl&lt;/code&gt; in the actual docs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model IDs&lt;/strong&gt;: &lt;code&gt;qwen-plus&lt;/code&gt; and &lt;code&gt;qwen-turbo&lt;/code&gt; still work as legacy aliases, but the current-generation family the docs actively promote are &lt;code&gt;qwen3.7-plus&lt;/code&gt; (balanced), &lt;code&gt;qwen3.7-max&lt;/code&gt; (heavy reasoning), and &lt;code&gt;qwen3.6-flash&lt;/code&gt; (fast + cheap). Embedding bumped from &lt;code&gt;text-embedding-v3&lt;/code&gt; → &lt;code&gt;text-embedding-v4&lt;/code&gt; too, which quietly added new supported dimensions (128, 256, 1536, 2048).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you're building on Qwen Cloud right now, the config that actually works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/config.py
&lt;/span&gt;&lt;span class="n"&gt;dashscope_api_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
&lt;span class="n"&gt;qwen_api_base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://dashscope-intl.aliyuncs.com/compatible-mode/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;qwen_model_plus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;qwen3.7-plus&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;qwen_model_turbo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;qwen3.6-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;qwen_embed_model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text-embedding-v4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;qwen_embed_dim&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, the env var is &lt;code&gt;DASHSCOPE_API_KEY&lt;/code&gt; — the &lt;em&gt;platform&lt;/em&gt; is called Qwen Cloud but the auth header inherits the DashScope name. I named my pydantic field &lt;code&gt;dashscope_api_key&lt;/code&gt; to match the docs' convention, and the code started reading like it was written &lt;strong&gt;for&lt;/strong&gt; Qwen Cloud rather than adapted to it. Small thing, matters when judges read your repo.&lt;/p&gt;

&lt;h2&gt;
  
  
  One orchestrator, four gateways
&lt;/h2&gt;

&lt;p&gt;The design bet was: &lt;strong&gt;all four channels go through the same LangGraph orchestrator, the same tool layer, the same pgvector memory, the same secret redactor.&lt;/strong&gt; No per-channel business logic beyond parsing.&lt;/p&gt;

&lt;p&gt;WhatsApp adapter, email adapter, web adapter, voice adapter — each is ~30 lines. They normalize their inbound payload into a &lt;code&gt;{session_id, content, phone}&lt;/code&gt; triple and shove it into:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ainvoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;HumanMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;session_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;phone&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;configurable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thread_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sid&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything after that — triage, memory recall, tool calls, response generation, outbound secret redaction — runs identically across channels. The Chinese message that just booked an appointment in the web widget exercises exactly the same code path as a Nigerian patient's voice call — whether they dialed the clinic's number or clicked to call from a browser tab.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The parity is not aesthetic; it's the point.&lt;/strong&gt; It means the HITL escalation works the same way for every channel. It means recall of "this patient is allergic to penicillin" surfaces whether they're on voice or email. It means when I ship a new tool — say, a "reschedule" — it works everywhere at once.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;AsyncPostgresSaver&lt;/code&gt; checkpointer sits behind it all so multi-turn conversations survive process restarts. When the container crash-loops (which it did for real during my Alibaba deployment adventures — long story, in &lt;code&gt;docs/DEPLOY_ALIBABA_ECS.md&lt;/code&gt;), no conversation state is lost.&lt;/p&gt;

&lt;h2&gt;
  
  
  The multilingual recall thing
&lt;/h2&gt;

&lt;p&gt;pgvector, &lt;code&gt;text-embedding-v4&lt;/code&gt; at 1024 dimensions, with a decay-weighted re-ranker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;importance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;similarity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;importance&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;05&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;days_old&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;recency_weight&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;memories&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;patient_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;similarity&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;recency_weight&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The multilingual part is free — the embedding model handles it. &lt;code&gt;患者对青霉素过敏&lt;/code&gt; (patient is allergic to penicillin) and &lt;code&gt;Patient is penicillin-allergic&lt;/code&gt; land in the same vector neighborhood, so a Mandarin patient's memory retrieved for an English message just... works. Zero language routing, zero translation step.&lt;/p&gt;

&lt;h2&gt;
  
  
  What surprised me
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;qwen3.7-plus&lt;/code&gt; speaks fluent Mandarin without a single locale prompt.&lt;/strong&gt; The demo booking flow returns properly formatted Chinese dates (&lt;code&gt;2026年7月3日 上午 9:00&lt;/code&gt;) unprompted. I have exactly zero Chinese in the system prompt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The full booking round-trip is two LLM calls, not one.&lt;/strong&gt; Triage → recall → tool → generate. Cold-start ~8s, warm ~5–6s. If you want sub-3-second replies, you have to route triage to the Flash model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alibaba Cloud CLI's &lt;code&gt;--output json&lt;/code&gt; flag is table-only.&lt;/strong&gt; JSON is the default. I lost 15 minutes to &lt;code&gt;bad flag format --output with field cols= required&lt;/code&gt;. Every CLI on Earth has &lt;code&gt;--output json&lt;/code&gt;; this one has it &lt;em&gt;inverted&lt;/em&gt;. Log this in your muscle memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The stack, if you're grepping
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Orchestrator&lt;/strong&gt;: LangGraph 1.2 + &lt;code&gt;AsyncPostgresSaver&lt;/code&gt; checkpoints&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LLM&lt;/strong&gt;: &lt;code&gt;qwen3.7-plus&lt;/code&gt; for generation, &lt;code&gt;qwen3.6-flash&lt;/code&gt; for classification, via DashScope OpenAI-compatible endpoint&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embeddings&lt;/strong&gt;: &lt;code&gt;text-embedding-v4&lt;/code&gt; at 1024 dims into pgvector on Postgres 16&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Voice&lt;/strong&gt;: Pipecat (Twilio phone + a self-hosted browser call widget) with &lt;code&gt;qwen3.7-plus&lt;/code&gt; LLM + Deepgram STT + ElevenLabs TTS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ingress&lt;/strong&gt;: FastAPI + slowapi rate limiter + Caddy 2 TLS reverse proxy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment&lt;/strong&gt;: Docker Compose on Alibaba Cloud ECS &lt;code&gt;ecs.e-c1m2.large&lt;/code&gt; in Singapore&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Human-in-loop&lt;/strong&gt;: FastAPI + HTMX + SSE dashboard at &lt;code&gt;/staff&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tests&lt;/strong&gt;: 217 passing, plus a 33-case intent eval (97% accuracy) that includes three Mandarin cases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Six containers of complexity, ~7,200 lines of Python, one weekend's worth of Alibaba Cloud console clicks, and a small amount of yelling at PowerShell's argument parser.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you're building on Qwen Cloud too
&lt;/h2&gt;

&lt;p&gt;Two things I'd tell past-me:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Read &lt;code&gt;docs.qwencloud.com/developer-guides/getting-started/introduction&lt;/code&gt; first.&lt;/strong&gt; That one page has the endpoint, the env var, and the model IDs. My code originally had all three wrong because I'd read old DashScope tutorials that predated the Qwen Cloud rebrand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't roll your own agent loop.&lt;/strong&gt; LangGraph + the OpenAI SDK do 90% of it out of the box. The interesting engineering is in the &lt;em&gt;tools&lt;/em&gt; (the calendar, the memory, the redactor) and the &lt;em&gt;escape hatches&lt;/em&gt; (HITL, confidence thresholds), not in re-implementing what LangGraph already ships.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's the build.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repo: &lt;a href="https://github.com/Otitodev/Maindesk" rel="noopener noreferrer"&gt;github.com/Otitodev/Maindesk&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Live demo: &lt;a href="https://maindesk.otito.site/chat" rel="noopener noreferrer"&gt;maindesk.otito.site/chat&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docs: &lt;a href="https://github.com/Otitodev/Maindesk/blob/main/docs/DEPLOY_ALIBABA_ECS.md" rel="noopener noreferrer"&gt;DEPLOY_ALIBABA_ECS.md&lt;/a&gt;, &lt;a href="https://github.com/Otitodev/Maindesk/blob/main/docs/DEMO_SCRIPT.md" rel="noopener noreferrer"&gt;DEMO_SCRIPT.md&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Questions in the comments. If you're grinding on the hackathon too, good luck — submissions close July 20.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>langraph</category>
      <category>hackathon</category>
      <category>alibabachallenge</category>
    </item>
  </channel>
</rss>
