> ## Documentation Index
> Fetch the complete documentation index at: https://docs.interpscout.org/llms.txt
> Use this file to discover all available pages before exploring further.

# The Agent Team

> Producer, Briefing, and Cockpit — three agents with three narrow jobs

InterpScout doesn't have one do-everything assistant. It has three agents, each scoped to one artifact, plus a chat surface that deliberately cannot do agent work itself. Splitting responsibility this way keeps the system legible: each artifact has exactly one agent accountable for it, never a monolithic prompt where responsibility is diffuse.

<div style={{position: "relative", width: "100%", maxWidth: "980px", margin: "2rem auto"}}>
  <svg viewBox="0 0 1650 650" style={{width: "100%", height: "auto", display: "block"}} role="img" aria-label="Teacher and Cockpit enqueue work to a Postgres queue; a scheduled dispatcher hands it to the Producer and Briefing agents on the eve durable runtime, where an adversarial glossary reviewer checks Producer's work; both agents pass through mechanical gates before reaching the database and web UI; progress heartbeats flow back from the runtime to the activity live view.">
    <rect x="820" y="110" width="480" height="370" rx="16" fill="#8A8378" fillOpacity="0.05" stroke="#8A8378" strokeWidth="1.4" strokeDasharray="7 6" />

    <path d="M990 480 C990 610, 1470 610, 1470 575" stroke="#C8A55B" strokeWidth="1.6" strokeDasharray="5 5" fill="none" />

    <path d="M1470 575 L1474.5 588 L1465.5 588 Z" fill="#C8A55B" />

    <path d="M110.0 187.0 L110.0 287.0" stroke="#8A8378" strokeWidth="2" fill="none" />

    <path d="M110.0 300.0 L105.5 287.0 L114.5 287.0 Z" fill="#8A8378" />

    <path d="M212.0 340.0 L264.0 340.0" stroke="#8A8378" strokeWidth="2" fill="none" />

    <path d="M277.0 340.0 L264.0 344.5 L264.0 335.5 Z" fill="#8A8378" />

    <path d="M482.0 340.0 L524.0 340.0" stroke="#8A8378" strokeWidth="2" fill="none" />

    <path d="M537.0 340.0 L524.0 344.5 L524.0 335.5 Z" fill="#8A8378" />

    <path d="M761.8 309.8 L869.7 280.5" stroke="#8A8378" strokeWidth="2" fill="none" />

    <path d="M882.3 277.1 L870.9 284.9 L868.6 276.2 Z" fill="#8A8378" />

    <path d="M761.9 362.4 L869.4 383.9" stroke="#8A8378" strokeWidth="2" fill="none" />

    <path d="M882.2 386.4 L868.5 388.3 L870.3 379.5 Z" fill="#8A8378" />

    <path d="M1097.0 250.7 L1354.0 257.1" stroke="#8A8378" strokeWidth="2" fill="none" />

    <path d="M1367.0 257.4 L1353.9 261.6 L1354.1 252.6 Z" fill="#8A8378" />

    <path d="M1096.7 375.1 L1354.9 295.5" stroke="#8A8378" strokeWidth="2" fill="none" />

    <path d="M1367.4 291.6 L1356.3 299.8 L1353.6 291.2 Z" fill="#8A8378" />

    <path d="M1470.0 302.0 L1470.0 347.0" stroke="#8A8378" strokeWidth="2" fill="none" />

    <path d="M1470.0 360.0 L1465.5 347.0 L1474.5 347.0 Z" fill="#8A8378" />

    <path d="M1470.0 439.0 L1470.0 484.0" stroke="#8A8378" strokeWidth="2" fill="none" />

    <path d="M1470.0 497.0 L1465.5 484.0 L1474.5 484.0 Z" fill="#8A8378" />

    <path d="M1066.5 213.1 L1088.8 202.9" stroke="#C8A55B" strokeWidth="1.6" strokeDasharray="4 4" fill="none" />

    <rect x="35.0" y="120.0" width="150" height="60" rx="10" fill="#8A8378" fillOpacity="0.10" stroke="#8A8378" strokeWidth="1.4" />

    <rect x="15.0" y="308.0" width="190" height="64" rx="12" fill="#8A8378" fillOpacity="0.10" stroke="#8A8378" strokeWidth="1.4" />

    <rect x="285.0" y="308.0" width="190" height="64" rx="12" fill="#8A8378" fillOpacity="0.10" stroke="#8A8378" strokeWidth="1.4" />

    <rect x="545.0" y="308.0" width="210" height="64" rx="12" fill="#8A8378" fillOpacity="0.10" stroke="#8A8378" strokeWidth="1.4" />

    <rect x="890.0" y="216.0" width="200" height="64" rx="12" fill="#B5763F" fillOpacity="0.16" stroke="#B5763F" strokeWidth="1.6" />

    <rect x="1060.0" y="150.0" width="180" height="50" rx="10" fill="#C8A55B" fillOpacity="0.12" stroke="#C8A55B" strokeWidth="1.4" strokeDasharray="5 4" />

    <rect x="890.0" y="376.0" width="200" height="64" rx="12" fill="#B5763F" fillOpacity="0.16" stroke="#B5763F" strokeWidth="1.6" />

    <rect x="1375.0" y="225.0" width="190" height="70" rx="12" fill="#C8A55B" fillOpacity="0.16" stroke="#C8A55B" strokeWidth="1.6" />

    <rect x="1375.0" y="368.0" width="190" height="64" rx="12" fill="#8A8378" fillOpacity="0.10" stroke="#8A8378" strokeWidth="1.4" />

    <rect x="1370.0" y="505.0" width="200" height="70" rx="12" fill="#8A8378" fillOpacity="0.10" stroke="#8A8378" strokeWidth="1.4" />
  </svg>

  <div style={{position: "absolute", left: "50.9%", top: "9.5%", fontSize: "11px", fontWeight: 600, color: "#8A8378", letterSpacing: "0.02em", whiteSpace: "nowrap"}}>eve durable runtime</div>

  <div style={{position: "absolute", left: "74.5%", top: "97.5%", transform: "translate(-50%,-50%)", fontSize: "11.5px", fontStyle: "italic", color: "#8A8378", whiteSpace: "nowrap"}}>progress heartbeats → Activity live view</div>

  <div style={{position: "absolute", left: "6.67%", top: "23.08%", transform: "translate(-50%,-50%)", textAlign: "center", width: "9.1%"}}>
    <div style={{fontWeight: 700, fontSize: "14.5px"}}>Teacher</div>
  </div>

  <div style={{position: "absolute", left: "6.67%", top: "52.31%", transform: "translate(-50%,-50%)", textAlign: "center", width: "10.9%"}}>
    <div style={{fontWeight: 700, fontSize: "14.5px"}}>Cockpit</div>
    <div style={{fontSize: "10.5px", color: "#8A8378", marginTop: "2px", lineHeight: 1.25}}>enqueue-only console</div>
  </div>

  <div style={{position: "absolute", left: "23.03%", top: "52.31%", transform: "translate(-50%,-50%)", textAlign: "center", width: "10.9%"}}>
    <div style={{fontWeight: 700, fontSize: "14.5px"}}>Postgres queue</div>
    <div style={{fontSize: "10.5px", color: "#8A8378", marginTop: "2px", lineHeight: 1.25}}>queued rows</div>
  </div>

  <div style={{position: "absolute", left: "39.39%", top: "52.31%", transform: "translate(-50%,-50%)", textAlign: "center", width: "12.1%"}}>
    <div style={{fontWeight: 700, fontSize: "14.5px"}}>Scheduled dispatcher</div>
    <div style={{fontSize: "10.5px", color: "#8A8378", marginTop: "2px", lineHeight: 1.25}}>claims queued rows</div>
  </div>

  <div style={{position: "absolute", left: "60.00%", top: "38.15%", transform: "translate(-50%,-50%)", textAlign: "center", width: "11.5%"}}>
    <div style={{fontWeight: 700, fontSize: "14.5px"}}>Producer</div>
  </div>

  <div style={{position: "absolute", left: "69.70%", top: "26.92%", transform: "translate(-50%,-50%)", textAlign: "center", width: "10.3%"}}>
    <div style={{fontWeight: 700, fontSize: "12.5px"}}>Adversarial reviewer</div>
    <div style={{fontSize: "10px", color: "#8A8378", marginTop: "1px", lineHeight: 1.2}}>skeptical pass</div>
  </div>

  <div style={{position: "absolute", left: "60.00%", top: "62.77%", transform: "translate(-50%,-50%)", textAlign: "center", width: "11.5%"}}>
    <div style={{fontWeight: 700, fontSize: "14.5px"}}>Briefing</div>
    <div style={{fontSize: "10.5px", color: "#8A8378", marginTop: "2px", lineHeight: 1.25}}>research + writing</div>
  </div>

  <div style={{position: "absolute", left: "89.09%", top: "40.00%", transform: "translate(-50%,-50%)", textAlign: "center", width: "11.8%"}}>
    <div style={{fontWeight: 700, fontSize: "14.5px"}}>Mechanical gates</div>
    <div style={{fontSize: "10.5px", color: "#8A8378", marginTop: "2px", lineHeight: 1.25}}>verify, don't trust</div>
  </div>

  <div style={{position: "absolute", left: "89.09%", top: "61.54%", transform: "translate(-50%,-50%)", textAlign: "center", width: "12.7%"}}>
    <div style={{fontWeight: 700, fontSize: "14.5px"}}>Database</div>
    <div style={{fontSize: "10.5px", color: "#8A8378", marginTop: "2px", lineHeight: 1.25}}>courses · briefings · terms</div>
  </div>

  <div style={{position: "absolute", left: "89.09%", top: "83.08%", transform: "translate(-50%,-50%)", textAlign: "center", width: "13.3%"}}>
    <div style={{fontWeight: 700, fontSize: "14.5px"}}>Web UI</div>
    <div style={{fontSize: "10.5px", color: "#8A8378", marginTop: "2px", lineHeight: 1.25}}>courses / briefings / activity</div>
  </div>
</div>

*Terracotta marks the two agents; gold marks the system's two trust mechanisms — the adversarial reviewer inside course production, and the mechanical gates every artifact must clear before it reaches the database. Cockpit only ever enqueues; it cannot run agent work itself.*

## Producer — course production

Given a bilingual source URL (or a teacher-uploaded file), the Producer agent turns it into a parallel-reading course. It runs as a durable, long-lived session — not a single request-response call — because the work genuinely takes minutes: fetching the source, cleaning and aligning it paragraph by paragraph, reading through the whole document window by window to curate a glossary, sending that glossary to an adversarial reviewer sub-agent for a second, skeptical pass, and revising until a mechanical acceptance gate lets it through.

The full mechanics — the sandbox files it works in, the review sub-agent, the dozen-plus gates a glossary has to clear — are in [Document Workshop](/internals/document-workshop).

## Briefing — pre-meeting preparation

Given a meeting topic (and optionally a speaker, host organization, and focus notes), the Briefing agent researches the open web, cross-checks what it finds, and writes a structured pre-meeting knowledge briefing: domain crash course, institution and speaker profiles, contested issues, a graded bilingual term table, and further reading. It runs on the same durable infrastructure as the Producer, because the same problem applies — real research takes real time, and the agent needs to survive longer than a single HTTP request.

The queue, the heartbeat discipline, and the save gate are in [Briefing Pipeline](/internals/briefing-pipeline).

## Cockpit — the teacher's dispatch console

Cockpit is the chat interface teachers see at `/studio`. It looks like it could delegate straight to Producer or Briefing, but it structurally can't: it isn't a durable agent session at all. It's a plain streaming chat endpoint with a couple of narrow tools — enqueue a source for production, enqueue a briefing request — and nothing else. When a teacher says "produce this document" or "prepare a briefing on this meeting," Cockpit writes a queued row to Postgres and replies immediately. A separate dispatcher, running on a schedule, is what actually hands the work to Producer or Briefing.

This split is a deliberate piece of failure isolation. A chat interface and a long-running production job have opposite availability needs: the chat must answer in seconds, every time; the job may legitimately spend many minutes on research and gates. Running them in separate runtimes means no slow tool call deep inside a production session can ever hold the teacher's console hostage — a chat request has a hard time limit, and the heavy work happens somewhere it can take its time.

<Card title="Why agents, not a chatbot" icon="circle-question" href="/internals/truth-layer">
  Cockpit answers questions and takes dispatch requests. It does not produce artifacts. The philosophy behind that separation — and why every artifact is verified mechanically rather than trusted on the agent's word — is covered in Truth Layer.
</Card>

## What ties them together

Producer and Briefing don't share a code path, but they share a database: every course the Producer curates deposits its terms — with grading and sourcing — into the same terminology base that the reader UI highlights against and that later briefings draw context from. A teacher who has produced thirty courses on trade policy has, without asking for it, built a glossary that makes the thirty-first briefing on trade policy better sourced. See [Terminology base](/concepts/terminology-base) for how that shared store is structured and searched.

All three agents currently run on DeepSeek's `deepseek-v4-pro` reasoning model for text work. The one place a different model shows up is scoring student audio, which is a genuinely different task — see [Architecture](/internals/architecture) for the full model stack.
