TUCAN Agent Types — Specialist, Network, Operator and Workflow Agents
Audiences: developer, internal
"Agent type" in TUCAN is overloaded — there are FIVE distinct concept layers that all use the word "agent." This page lays them out: coarse verticals (
AgentTypeKey), template-driven specialists (clinical / scheduling / document / admin / tucan / deep-search), the network orchestrator, the dedicated voice Operator agent, and per-step workflow agents. Knowing which "agent" you're talking about prevents 90% of TUCAN onboarding confusion.
Business Purpose
Different clinical surfaces have different shapes:
- A doctor at the desk wants a fast, deterministic specialist per task — clinical for chart actions, scheduling for booking.
- The voice channel needs a low-latency Operator that delegates to TUCAN for hard work but keeps trivial replies conversational.
- Multi-step clinical workflows (intake, prescribe-and-check, agentic-diagnosis) need per-step workflow agents that are not the same as the full specialist.
- The future evolution wants network orchestration — one supervisor that delegates to multiple specialists for cross-domain queries.
Agent types let Dudoxx surface the right tool catalog + the right prompt + the right latency budget per channel. This is also where "reply to operator only on voice" (the FSM rule) lives.
Audiences
- Developer / partner: Five layers of "agent" — read this page before reading registry code. Once you know which layer you're in, the code reads cleanly.
- Internal (ops / support): When a session reports the wrong
agent answered,
session.agentTypeis the variable to query;AgentTypeKeyis the typed enum.
Architecture
There are five distinct concepts in this codebase that share
the word "agent." agent-type.registry.ts:74-77 calls this out
explicitly.
1) AgentTypeKey — coarse vertical categories (5 keys)
agent-type.registry.ts:25 declares:
export const AGENT_TYPE_KEYS = [ 'tucan', 'diagnosis', 'intake', 'visit', 'meeting', ] as const; export type AgentTypeKey = (typeof AGENT_TYPE_KEYS)[number];
These are vertical product surfaces, not LLM agents — each maps to an entity type the session is built around. A session has exactly one vertical:
tucan— generic chat (default entity: patient)diagnosis— diagnostic engine sessionsintake— intake conversationsvisit— chart capture during a visitmeeting— meeting assistant
Each vertical's metadata (AgentTypeMetadata) carries displayName,
defaultEntityRefType, factoryHint, optional sessionType.
2) Specialist agents (template-driven, see [[agent-templates]])
YAML-defined Mastra agents under tucan/templates/agents/:
clinical— chart, FHIR, conditions, medications, vitals, allergies, assessment, visitscheduling— slots, appointments, FHIR Appointment/Slotdocument— doxing, templates, generation, OCRadmin— billing, insurance, taskstucan— full-catalog all-categories agentdeep-search— Qdrant + document RAG search
Created by SpecialistAgentFactory.create* per turn from the
template. Each emits agent:resolved so the frontend knows which
specialist answered.
3) Network orchestrator agent
NetworkAgentFactory.createNetworkAgent produces a supervisor
Mastra agent that delegates to multiple specialists for
cross-domain queries (e.g. "schedule a follow-up AND draft the
referral letter"). Marked for refactor to a single supervisor
with tool-based specialist delegation — the source file header
explicitly calls out this future migration.
4) Voice Operator agent (2-layer gateway)
tucan/agents/operator.agent.ts + the entire
tucan-operator/agent/ module: a thin Mastra gateway with 4
tools that fronts TUCAN for the voice channel:
delegate-to-tucan— hand the turn to the full TUCAN dispatcher (the heavy lift).reply-to-operator-direct— answer the user directly without calling TUCAN (latency-sensitive trivial paths).get-operator-context— fetch operator-specific context (current speaker, audio session ID, etc.).voice-control— barge-in, pause, resume.
The TUCAN agent itself receives reply-to-operator (the voice
reply tool) ONLY when isVoiceSession is true. This is the
"reply to operator only on voice" FSM rule
([[feedback_voice_state_machine_design]] and TUCAN AI memory
shard, "voice-only since 2026-04-01").
5) Per-step workflow agents
Mastra workflows (tucan/workflows/) embed agents inside their
steps:
agents/workflow-step.agent.ts— generic per-step LLM agentagents/knowledge-curator.agent.ts— knowledge curation (agents/knowledge-curator/) — its own multi-step workflowagents/prompt-rewriter.agent.ts— cheap rewriter used by RewriterStageagents/trivial-bypass.agent.ts— registered but production uses the deterministic classifieragents/quick-action.agent.ts/agents/quick-actions.agent.ts— propose follow-up actionsagents/reporter.agent.ts— narrate dispatcher outputagents/tucan-docgen.agent.ts— document generationagents/tucan-summarization.agent.ts— summarizationagents/patient-assistant.agent.ts— patient-side assistantagents/meeting-assistant.agent.ts— meeting transcript + follow-upagents/tucan-operator.agent.ts— variant for operator voice flowsagents/specialist.agent.ts/agents/network.agent.ts/agents/tucan.agent.ts— base MastraAgentconstructors consumed by the factories
Tech Stack & Choices
| Component | Choice | Why |
|---|---|---|
AgentTypeKey | as const literal union | Compile-time exhaustive; new vertical = one edit + one registry entry. |
| Specialist creation | YAML template + SpecialistAgentFactory | One readable surface for prompt + tool categories + LLM defaults. |
| Voice operator | Separate 4-tool gateway agent | Latency budget: voice cannot afford TUCAN's full per-turn pipeline for trivial chat. |
| Network agent | Mastra 1.x networks with memory on the orchestrator | Required by Mastra for cross-specialist conversation continuity (network-factory.ts:124-125). |
| Workflow step agents | Mastra createStep with embedded agent.generate | Per-step agent allows different model per step (planner vs executor vs reporter). |
| Resolution | agent-type-router.ts declares `ResolvedFactoryKind = 'network' | 'specialist'` |
| Model resolution | Always from context.llmConfig | NEVER explicit on new Agent({...}) — [[feedback_agent_model_inheritance]]. |
Data Flow
Business outcome: A patient calls; the voice channel answers; the Operator agent handles "hi, can I book an appointment?" by replying directly, then delegates the actual slot picker to TUCAN — under 200 ms of voice latency on the trivial reply.
Technical mechanism:
- LiveKit Python worker bridges audio → STT → TUCAN voice pipeline.
peer-bridge.servicecallsOperatorAgent.generate(...)(ddx-api/src/ai/tucan-operator/agent/operator-agent.factory.ts).- The operator agent's 4 tools are wired:
- For "hi" → calls
reply-to-operator-direct→ STT/TTS pipeline immediately, no TUCAN dispatch.- For "book an appointment" → calls
delegate-to-tucanwith intent + entity refs; TUCAN clinical/scheduling specialist runs in the background.- TUCAN's scheduling specialist runs the full
AgentDispatcherService.processMessagepipeline; the operator stays responsive.reply-to-operatoris injected into the TUCAN tool catalog ONLY becauseisVoiceSession === true. Outside voice it is not in the catalog; the LLM cannot call it.
Implicated Code
ddx-api/src/ai/tucan/registry/agent-type.registry.ts:25—AGENT_TYPE_KEYSliteral array.ddx-api/src/ai/tucan/registry/agent-type.registry.ts:33—export type AgentTypeKey = (typeof AGENT_TYPE_KEYS)[number].ddx-api/src/ai/tucan/registry/agent-type.registry.ts:35—ENTITY_REF_TYPESliteral array.ddx-api/src/ai/tucan/registry/agent-type.registry.ts:51—interface AgentTypeMetadata.ddx-api/src/ai/tucan/registry/agent-type.registry.ts:74-77— the "three distinct concepts" naming clarification comment.ddx-api/src/ai/tucan/registry/agent-type.registry.ts:96— classAgentTypeRegistry.ddx-api/src/ai/tucan/registry/agent-type.registry.ts:108—registerAgentType(key, metadata).ddx-api/src/ai/tucan/registry/agent-type.registry.ts:118—resolveByKey(key).ddx-api/src/ai/tucan/registry/agent-type-router.ts:21—ResolvedFactoryKind = 'network' | 'specialist'.ddx-api/src/ai/tucan/registry/specialist-factory.ts:55— classSpecialistAgentFactory.ddx-api/src/ai/tucan/registry/network-factory.ts:47— classNetworkAgentFactory.ddx-api/src/ai/tucan/registry/network-factory.ts:124-125— Mastra 1.x networks require memory on the orchestrator.ddx-api/src/ai/tucan/agents/specialist.agent.ts— base Mastra Agent constructor consumed by the specialist factory.ddx-api/src/ai/tucan/agents/network.agent.ts— base for network factory.ddx-api/src/ai/tucan/agents/operator.agent.ts— TUCAN-side operator entrypoint.ddx-api/src/ai/tucan/agents/tucan-operator.agent.ts— variant for operator voice flows.ddx-api/src/ai/tucan-operator/agent/operator-agent.factory.ts— voice Operator factory; binds 4 tools.ddx-api/src/ai/tucan-operator/agent/tools/delegate-to-tucan.tool.ts— delegate-to-TUCAN tool.ddx-api/src/ai/tucan-operator/agent/tools/reply-to-operator-direct.tool.ts— direct reply without TUCAN dispatch.ddx-api/src/ai/tucan-operator/agent/tools/get-operator-context.tool.ts— operator context.ddx-api/src/ai/tucan-operator/agent/tools/voice-control.tool.ts— voice barge / pause.ddx-api/src/ai/tucan/agents/workflow-step.agent.ts— per-step workflow agent.ddx-api/src/ai/tucan/agents/knowledge-curator.agent.ts— knowledge curator (multi-step workflow agent).ddx-api/src/ai/tucan/agents/prompt-rewriter.agent.ts— cheap rewriter.ddx-api/src/ai/tucan/agents/reporter.agent.ts— reporter narration agent.ddx-api/src/ai/tucan/agents/quick-actions.agent.ts— quick actions agent (temp 0.3, maxTokens 512, no tools).ddx-api/src/ai/tucan/agents/patient-assistant.agent.ts— patient-side assistant.ddx-api/src/ai/tucan/agents/meeting-assistant.agent.ts— meeting assistant.ddx-api/src/ai/tucan/agents/tucan.agent.ts— full-catalog TUCAN agent base.ddx-api/src/ai/tucan/tools/voice/reply-to-operator.tool.ts— the tool injected ONLY whenisVoiceSessionis true.
Operational Notes
- "Agent type" is overloaded. When someone says "agent type,"
ask which of the five layers they mean:
AgentTypeKeyvertical, specialist template, network supervisor, voice operator, or workflow step agent. The registry source file calls this out in comments at line 74-77. session.agentTypestrings in the wild include'clinical'/'scheduling'/'document'/'admin'/'tucan'/'flowagent'/'clinical-assistant'. These are specialist identifiers (or the FlowAgent route), separate from theAgentTypeKey5-vertical enum. Do not conflate.useSessionResolverALWAYS creates'clinical-assistant'— does NOT forward the user-selected type. This is a known defect in the EmbeddableAssistant frontend layer (MEMORY_TUCAN_AI). File a fix; do not work around per call.reply-to-operatoris voice-only since 2026-04-01. Injected into the TUCAN catalog only whenisVoiceSession === true(agent-dispatcher.service.ts:172).- Network agent is deprecated for new product. Source
comments call out the planned migration to a single
supervisor with tool-based specialist delegation. Don't
build new product on the network path; use the orchestrator
workflow (
orchestrated-dispatch) instead. - Mastra 1.x network memory. Mastra 1.x networks require
memory on the orchestrator
(
network-factory.ts:124-125); cross-specialist continuity depends on it. Mastra 2.x will change this contract; track the upgrade. - Ephemeral
new Agent(...)is banned outside allowlisted factory sites ([[ddx-mastra-specialist_memory.md]] 2026-04-28). The allowlist is essentially the registry + per-purpose factories listed here. - Quick actions agent uses temp 0.3, maxTokens 512, no tools. Fire-and-forget at step 10 of the dispatcher pipeline (MEMORY_TUCAN_AI).
- Knowledge curator is its own workflow. Don't confuse it
with the curator role — the agent is a Mastra workflow
under
agents/knowledge-curator/.
Related Topics
- [[tucan-assistant]] — dispatcher entry that resolves which agent type to invoke.
- [[agent-templates]] — the YAML factory pattern for specialists.
- [[tucan-pool]] — pool that manages constructed agent instances per tenant.
- [[tucan-dispatcher]] — pipeline that calls the resolved agent via DispatcherStage.
- [[ai-medical-tools]] — catalog filtered per agent type by category.
- [[tucan-rag-tools]] — build-time tool-RAG ranking per agent template.
MEMORY_TUCAN_AIshard — agent types historical notes.feedback_voice_state_machine_design— voice FSM and reply-to-operator scope.