<?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: Rishi Kumar</title>
    <description>The latest articles on DEV Community by Rishi Kumar (@sonicboom15).</description>
    <link>https://dev.to/sonicboom15</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3927417%2F6d8d7b92-1f1f-4802-89d7-37b3251c6288.png</url>
      <title>DEV Community: Rishi Kumar</title>
      <link>https://dev.to/sonicboom15</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sonicboom15"/>
    <language>en</language>
    <item>
      <title>Build a Medical Chart Coding Pipeline with Daimon, Claude, and Neo4j</title>
      <dc:creator>Rishi Kumar</dc:creator>
      <pubDate>Tue, 12 May 2026 14:42:30 +0000</pubDate>
      <link>https://dev.to/sonicboom15/build-a-medical-chart-coding-pipeline-with-daimon-claude-and-neo4j-51ba</link>
      <guid>https://dev.to/sonicboom15/build-a-medical-chart-coding-pipeline-with-daimon-claude-and-neo4j-51ba</guid>
      <description>&lt;p&gt;Adding an LLM to your application usually means writing the same infrastructure over and over: define JSON schemas for each tool, dispatch tool calls, drive the agentic loop, wire up a vector store, manage embedding calls, handle session state. Before you know it the actual feature is buried under plumbing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/sonicboom15/daimon" rel="noopener noreferrer"&gt;Daimon&lt;/a&gt; is a Go sidecar that takes a different approach. Drop the binary next to your app, write a YAML config, and you get a fully operational LLM endpoint — with vector search, graph queries, session memory, and a complete agentic loop — without writing any of that wiring yourself.&lt;/p&gt;

&lt;p&gt;The key idea: when you declare a vector store or graph database in the config, Daimon &lt;strong&gt;auto-generates LLM tools&lt;/strong&gt; for it (&lt;code&gt;{name}_search&lt;/code&gt;, &lt;code&gt;{name}_cypher&lt;/code&gt;, etc.) and injects them into every LLM call. The model can use them immediately. You named the component; you got the tools.&lt;/p&gt;

&lt;p&gt;To show what this looks like end-to-end, we'll build a medical chart ICD-10 coding pipeline. Given a medical transcription, it will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Semantically search a vector store of 46k ICD-10 codes for candidates&lt;/li&gt;
&lt;li&gt;Verify each candidate against a Neo4j taxonomy graph&lt;/li&gt;
&lt;li&gt;Return only confirmed codes, with confidence scores grounded in the graph — not the model&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The entire LLM + tools setup fits in one YAML file. The Python client is about 60 lines. Let's build it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you'll need:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Python 3.11+&lt;/li&gt;
&lt;li&gt;An Anthropic API key (or swap to a fully local model — covered at the end)&lt;/li&gt;
&lt;li&gt;The Daimon binary&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1: Clone the Repo
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/sonicboom15/medchart
&lt;span class="nb"&gt;cd &lt;/span&gt;medchart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The repo contains everything: the Daimon config, the ICD-10 loader, and the coding pipeline. Here's the layout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;daimon-config/config.yaml   ← the entire LLM + tools setup&lt;/span&gt;
&lt;span class="s"&gt;docker-compose.yml          ← Neo4j, Qdrant, Ollama&lt;/span&gt;
&lt;span class="s"&gt;icd10/loader.py             ← CMS XML parser → Qdrant + Neo4j&lt;/span&gt;
&lt;span class="s"&gt;pipeline/coder.py           ← Daimon client → CodeAssignment[]&lt;/span&gt;
&lt;span class="s"&gt;pipeline/ingest.py          ← batch processor for MTSamples CSV&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 2: Install Daimon
&lt;/h2&gt;

&lt;p&gt;Pick the method for your platform:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;macOS / Linux — Homebrew&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew tap sonicboom15/tap
brew &lt;span class="nb"&gt;install &lt;/span&gt;daimon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Windows — winget&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;winget&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sonicboom15.daimon&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Windows — Scoop&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;scoop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sonicboom15&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;https://github.com/sonicboom15/scoop-bucket&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;scoop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;daimon&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Debian / Ubuntu&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Download the .deb from https://github.com/sonicboom15/daimon/releases/latest&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;dpkg &lt;span class="nt"&gt;-i&lt;/span&gt; daimon_&lt;span class="k"&gt;*&lt;/span&gt;_linux_amd64.deb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;RHEL / Fedora&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Download the .rpm from https://github.com/sonicboom15/daimon/releases/latest&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;rpm &lt;span class="nt"&gt;-i&lt;/span&gt; daimon_&lt;span class="k"&gt;*&lt;/span&gt;_linux_amd64.rpm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Build from source&lt;/strong&gt; (requires Go 1.23+)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/sonicboom15/daimon.git
&lt;span class="nb"&gt;cd &lt;/span&gt;daimon &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; make build
&lt;span class="c"&gt;# binary at ./bin/daimon&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify the install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;daimon &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 3: Start the Infrastructure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This starts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Qdrant&lt;/strong&gt; on port &lt;code&gt;6333&lt;/code&gt; — vector store for ICD-10 code embeddings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Neo4j&lt;/strong&gt; on ports &lt;code&gt;7474&lt;/code&gt; (browser) and &lt;code&gt;7687&lt;/code&gt; (Bolt) — taxonomy graph&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ollama&lt;/strong&gt; on port &lt;code&gt;11434&lt;/code&gt; — local embedding model&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Remove the &lt;code&gt;deploy:&lt;/code&gt; GPU block from &lt;code&gt;docker-compose.yml&lt;/code&gt; if you don't have an NVIDIA GPU.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pull the embedding model into Ollama:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; medchart-ollama-1 ollama pull nomic-embed-text
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the only model Ollama needs. The LLM itself uses the Anthropic API.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Understand the Config
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;daimon-config/config.yaml&lt;/code&gt;. This single file is the entire pipeline setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="c1"&gt;# Local embedder via Ollama (OpenAI-compatible endpoint)&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;embedder&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;embedding/openai&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;base_url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://localhost:11434/v1&lt;/span&gt;
      &lt;span class="na"&gt;api_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;
      &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nomic-embed-text&lt;/span&gt;
      &lt;span class="na"&gt;dimensions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;768"&lt;/span&gt;

  &lt;span class="c1"&gt;# 46k ICD-10 code descriptions in Qdrant&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;icd10&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;qdrant&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;base_url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://localhost:6333&lt;/span&gt;
      &lt;span class="na"&gt;collection&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;icd10&lt;/span&gt;
      &lt;span class="na"&gt;create_if_missing&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
      &lt;span class="na"&gt;embedder&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;embedder&lt;/span&gt;
      &lt;span class="na"&gt;dimensions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;768"&lt;/span&gt;

  &lt;span class="c1"&gt;# ICD-10 taxonomy hierarchy in Neo4j&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;icd10-graph&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;neo4j&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;bolt_url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bolt://localhost:7687&lt;/span&gt;
      &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;neo4j&lt;/span&gt;
      &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;medchart&lt;/span&gt;

  &lt;span class="c1"&gt;# Claude Sonnet — api_key read from ANTHROPIC_API_KEY env var&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;coder&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;anthropic&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;default_model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;claude-sonnet-4-6&lt;/span&gt;
    &lt;span class="na"&gt;defaults&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.1&lt;/span&gt;
      &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1024&lt;/span&gt;
      &lt;span class="na"&gt;system&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;You are a clinical coding assistant. Given a medical chart excerpt, identify&lt;/span&gt;
        &lt;span class="s"&gt;and assign the correct ICD-10-CM codes using this exact two-phase workflow:&lt;/span&gt;

        &lt;span class="s"&gt;PHASE 1 — Search:&lt;/span&gt;
        &lt;span class="s"&gt;Call icd10_search for each distinct clinical concept in the note.&lt;/span&gt;
        &lt;span class="s"&gt;Issue all searches in a single parallel batch.&lt;/span&gt;

        &lt;span class="s"&gt;PHASE 2 — Verify:&lt;/span&gt;
        &lt;span class="s"&gt;For each candidate code, call icd10_graph_cypher:&lt;/span&gt;
          &lt;span class="s"&gt;MATCH (n:Code {code: $code}) RETURN n.code, n.short_desc&lt;/span&gt;
        &lt;span class="s"&gt;Issue all verifications in a single parallel batch.&lt;/span&gt;
        &lt;span class="s"&gt;Only include codes where this query returns a result.&lt;/span&gt;

        &lt;span class="s"&gt;Return ONLY a JSON array — no prose, no markdown:&lt;/span&gt;
          &lt;span class="s"&gt;[{"code": "J30.1", "description": "Allergic rhinitis due to pollen"}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few things worth understanding here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wiring order matters.&lt;/strong&gt; Daimon resolves components top to bottom: embedders first, then vector stores (which can reference an embedder by name via &lt;code&gt;embedder: embedder&lt;/code&gt;), then graph stores, then LLMs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Auto-generated tools.&lt;/strong&gt; Because you declared &lt;code&gt;icd10&lt;/code&gt; (Qdrant) and &lt;code&gt;icd10-graph&lt;/code&gt; (Neo4j), the &lt;code&gt;coder&lt;/code&gt; LLM automatically gets these tools on every call — no code required:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;icd10_search&lt;/code&gt; — embed a query and search Qdrant&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;icd10_upsert&lt;/code&gt; — insert or update a code&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;icd10-graph_cypher&lt;/code&gt; — run any Cypher query against Neo4j&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The system prompt references &lt;code&gt;icd10_search&lt;/code&gt; and &lt;code&gt;icd10_graph_cypher&lt;/code&gt; by name. That's all the wiring there is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Batched tool calls.&lt;/strong&gt; The system prompt tells the model to issue all searches in one batch and all verifications in another. Daimon executes concurrent tool calls in parallel, so two waves of 8 calls runs as fast as two single calls.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: Start Daimon
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sk-ant-...
daimon serve &lt;span class="nt"&gt;--config&lt;/span&gt; daimon-config/config.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see all four components register:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;INFO registered embedder       name=embedder    type=embedding/openai
INFO registered vector store   name=icd10       type=qdrant
INFO registered graph store    name=icd10-graph type=neo4j
INFO registered LLM component  name=coder       type=anthropic
INFO daimon listening          addr=127.0.0.1:3500
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 6: Load the ICD-10 Data
&lt;/h2&gt;

&lt;p&gt;Download the CMS 2025 ICD-10-CM tabular XML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://www.cms.gov/files/zip/2025-code-tables-tabular-and-index.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Extract &lt;code&gt;icd10cm_tabular_2025.xml&lt;/code&gt; into the &lt;code&gt;data/&lt;/code&gt; folder. Then install dependencies and run the loader:&lt;br&gt;
&lt;/p&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="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;".[dev]"&lt;/span&gt;
python &lt;span class="nt"&gt;-m&lt;/span&gt; icd10.loader data/icd10cm_tabular_2025.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The loader does three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Parses the XML.&lt;/strong&gt; The CMS file is a nested hierarchy of chapters → sections → diagnosis codes → subcodes. The parser walks this tree recursively and produces a flat list of &lt;code&gt;ICD10Code&lt;/code&gt; objects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Loads into Qdrant.&lt;/strong&gt; Each code is upserted via Daimon's &lt;code&gt;/v1/memory/icd10&lt;/code&gt; endpoint with the full description as content and the code, category, block, and chapter as metadata. IDs are deterministic &lt;code&gt;uuid5&lt;/code&gt; hashes of the code string, so re-runs are idempotent.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Loads into Neo4j.&lt;/strong&gt; The taxonomy becomes a graph via Daimon's &lt;code&gt;/v1/graph/icd10-graph/cypher&lt;/code&gt; endpoint:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="n"&gt;Chapter&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:PART_OF&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Block&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:PART_OF&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Category&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:IS_A&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Code&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All codes get a &lt;code&gt;:Code&lt;/code&gt; label; 3-character codes (like &lt;code&gt;J30&lt;/code&gt;, &lt;code&gt;E66&lt;/code&gt;) also get &lt;code&gt;:Category&lt;/code&gt;. Everything is batched into groups of 500 using Cypher &lt;code&gt;UNWIND&lt;/code&gt; to keep it fast and memory-efficient.&lt;/p&gt;

&lt;p&gt;This takes about 10 minutes. When it finishes, verify the counts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Vector store: should show ~46k points&lt;/span&gt;
curl http://localhost:6333/collections/icd10 | python &lt;span class="nt"&gt;-m&lt;/span&gt; json.tool
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the Neo4j browser at &lt;code&gt;http://localhost:7474&lt;/code&gt; (user: &lt;code&gt;neo4j&lt;/code&gt;, password: &lt;code&gt;medchart&lt;/code&gt;) and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="k"&gt;MATCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;n:&lt;/span&gt;&lt;span class="n"&gt;Code&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 7: Run the Coder
&lt;/h2&gt;

&lt;p&gt;Download &lt;code&gt;mtsamples.csv&lt;/code&gt; from &lt;a href="https://www.kaggle.com/datasets/tboyle10/medicaltranscriptions" rel="noopener noreferrer"&gt;Kaggle&lt;/a&gt; and save it to &lt;code&gt;data/&lt;/code&gt;. Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; pipeline.ingest &lt;span class="nt"&gt;--csv&lt;/span&gt; data/mtsamples.csv &lt;span class="nt"&gt;--out&lt;/span&gt; data/coded.jsonl &lt;span class="nt"&gt;--limit&lt;/span&gt; 10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll see the agentic tool calls stream in real time as Daimon drives the loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Allergic Rhinitis
  → icd10_search allergic rhinitis seasonal
  → icd10_search asthma mild intermittent
  → icd10_graph_cypher J30.9
  → icd10_graph_cypher J45.20
  ✓ J30.9  Allergic rhinitis, unspecified          (100%)
  ✓ J45.20 Mild intermittent asthma, uncomplicated (100%)

Laparoscopic Gastric Bypass Consult
  → icd10_search morbid obesity BMI
  → icd10_search gastroesophageal reflux
  → icd10_search knee pain bilateral
  → icd10_search low back pain
  → icd10_search nicotine dependence cigarettes
  → icd10_search allergy penicillin
  → icd10_graph_cypher E66.01
  → icd10_graph_cypher K21.9
  → icd10_graph_cypher M25.561
  → icd10_graph_cypher M25.562
  → icd10_graph_cypher M54.50
  → icd10_graph_cypher F17.210
  → icd10_graph_cypher Z88.0
  ✓ E66.01  Morbid (severe) obesity due to excess calories    (100%)
  ✓ K21.9   Gastro-esophageal reflux disease w/o esophagitis (100%)
  ✓ M25.561 Pain in right knee                               (100%)
  ✓ M25.562 Pain in left knee                                (100%)
  ✓ M54.50  Low back pain, unspecified                       (100%)
  ✓ F17.210 Nicotine dependence, cigarettes, uncomplicated   (100%)
  ✓ Z88.0   Allergy status to penicillin                     (100%)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each record in &lt;code&gt;coded.jsonl&lt;/code&gt; looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sample_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Laparoscopic Gastric Bypass Consult"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"specialty"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bariatrics"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"codes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"E66.01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Morbid (severe) obesity due to excess calories"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"verified"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"K21.9"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Gastro-esophageal reflux disease without esophagitis"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"verified"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"M25.561"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Pain in right knee"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"verified"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"M25.562"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Pain in left knee"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"verified"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"M54.50"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Low back pain, unspecified"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"verified"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"F17.210"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Nicotine dependence, cigarettes, uncomplicated"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"verified"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Z88.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allergy status to penicillin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"verified"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice &lt;code&gt;M25.561&lt;/code&gt; and &lt;code&gt;M25.562&lt;/code&gt; — bilateral knee pain correctly split into separate laterality codes. That's proper ICD-10 specificity, and the model inferred it from the clinical language without any special instruction.&lt;/p&gt;

&lt;p&gt;The confidence scores come from the graph verification step in &lt;code&gt;pipeline/coder.py&lt;/code&gt;, not from the model's own calibration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;1.0&lt;/code&gt; — exact code confirmed in Neo4j. Use it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0.5&lt;/code&gt; — category exists but specific subcode does not. Flag for human review.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0.0&lt;/code&gt; — not found at all. Hallucinated. Discard.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Bonus: Run Fully Local (No API Key)
&lt;/h2&gt;

&lt;p&gt;Swap two lines in &lt;code&gt;daimon-config/config.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;coder&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;llamacpp&lt;/span&gt;        &lt;span class="c1"&gt;# was: anthropic&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;base_url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://localhost:11434/v1&lt;/span&gt;
      &lt;span class="na"&gt;api_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;
      &lt;span class="na"&gt;default_model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;qwen2.5:7b&lt;/span&gt;   &lt;span class="c1"&gt;# was: default_model: claude-sonnet-4-6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pull the model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; medchart-ollama-1 ollama pull qwen2.5:7b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart Daimon. Everything else — the Qdrant store, the Neo4j graph, the Python scripts — stays identical. &lt;code&gt;qwen2.5:7b&lt;/code&gt; is accurate enough for most records during development. &lt;code&gt;qwen2.5:14b&lt;/code&gt; gets you meaningfully closer to Claude quality if you have the VRAM.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Actually Happening
&lt;/h2&gt;

&lt;p&gt;It's worth stepping back to see what Daimon is doing behind the scenes, because the Python client code is surprisingly short:&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="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;daimon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&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;http://localhost:3500&lt;/span&gt;&lt;span class="sh"&gt;"&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;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;coder&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;converse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;messages&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;role&lt;/span&gt;&lt;span class="sh"&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;user&lt;/span&gt;&lt;span class="sh"&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;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;chart_text&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&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&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;text_chunks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That single &lt;code&gt;converse&lt;/code&gt; call triggers a full agentic workflow inside Daimon:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Daimon calls Claude with the chart text and the auto-generated tool definitions for &lt;code&gt;icd10_search&lt;/code&gt; and &lt;code&gt;icd10_graph_cypher&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Claude calls &lt;code&gt;icd10_search&lt;/code&gt; for each clinical concept — Daimon embeds the query via Ollama and searches Qdrant, all in parallel&lt;/li&gt;
&lt;li&gt;Claude calls &lt;code&gt;icd10_graph_cypher&lt;/code&gt; to verify each candidate code — Daimon runs the Cypher queries against Neo4j, again in parallel&lt;/li&gt;
&lt;li&gt;Claude returns the final JSON array&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;converse&lt;/code&gt; generator yields text chunks back to your code&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your code never touched an embedding client, a Qdrant client, a Neo4j session, or an agentic loop. The YAML config wired all of it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where To Go From Here
&lt;/h2&gt;

&lt;p&gt;The full source is at &lt;a href="https://github.com/sonicboom15/medchart" rel="noopener noreferrer"&gt;github.com/sonicboom15/medchart&lt;/a&gt;.&lt;br&gt;
Daimon itself is at &lt;a href="https://github.com/sonicboom15/daimon" rel="noopener noreferrer"&gt;github.com/sonicboom15/daimon&lt;/a&gt; — it supports OpenAI, Anthropic, and any Ollama-compatible model, with Qdrant, Chroma, pgvector, Redis, Neo4j, and Memgraph as backends.&lt;/p&gt;

&lt;p&gt;The pattern here — vector search + graph verification + agentic LLM loop — applies to a lot of domains beyond medical coding. If you're building something similar and find yourself writing the same infrastructure glue, Daimon is worth a look.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>tutorial</category>
      <category>go</category>
    </item>
  </channel>
</rss>
