03 — Triage Agents
The triage agents: their roles, scopes, and boundaries inside the governed classification path.
The triage system uses three distinct agents, each with a specific role.
Agent Registry
| Agent | Service | Role | Authority |
|---|---|---|---|
| TriageAgent (runtime) | iw-agent-runtime | Intake classifier | Operational state only |
| TriageAgent (cognitive) | intelligence | Deep evaluation | Candidate staging only |
| Triage Bot | knowledge | AI extraction + Slack | Pending candidates only |
1. Runtime TriageAgent (iw-agent-runtime)
File: services/iw-agent-runtime/src/agents/triage-agent.ts
Type: Durable Object Agent (extends Agent<Env, TriageState>)
Role: First-line intake classifier. Receives raw events and routes them by simple pattern matching.
State Model
interface TriageState {
tenant_id: string;
rules: TriageRule[];
items: TriageItem[];
last_sweep_at?: string;
updated_at: string;
}
interface TriageItem {
id: string;
kind: "ai_chat" | "twin_session" | "worker_handoff" | "ingest" | "manual";
content: string;
route: "memory" | "proposal" | "signal" | "governance";
status: "open" | "resolved" | "escalated";
created_at: string;
resolved_at?: string;
}
Classification Rules
Default rules (configurable via addRule()):
| Rule ID | Pattern | Priority | Route |
|---|---|---|---|
| approval | "approve" | 100 | governance |
| decision | "decide" | 90 | proposal |
| signal | "signal" | 50 | signal |
| (default) | (no match) | — | memory |
Execution Flow
triage()receives input (kind, content, source, metadata)classify(content)matches against rules → determines route- Writes
triage_itemto SQLite (operational state) - If route is
memoryorsignal, callsemitTriageInput()to Continuity service - Returns
{ itemId, route, status: "open" }
What It Writes
triage_itemstable (Durable Object SQLite) — operational state only- Continuity event via
emitTriageInput()— evidence emission
What It Never Writes
- Canonical organizational memory
- Approved knowledge
- Entity state
2. Cognitive TriageAgent (intelligence)
File: services/intelligence/src/agents/specialized/triage.ts
Type: Workflow agent (extends BaseAgent)
Role: Deep cognitive evaluation of high-stakes content. Uses LLM reasoning across 4 dimensions.
Cognitive Dimensions
- Intelligent Categorization — What is the true intent?
- Contextual Linking — How does this relate to canonical memory?
- Canonical Review — Stale? Duplicate? Conflicts?
- Guardrails & Governance — Sensitivity → stage or reject?
Output Schema
{
"classification": {
"doc_type": "<string>",
"workflow_type": "<string>",
"intent": "<string>"
},
"canonical_review": {
"is_duplicate": boolean,
"has_conflict": boolean,
"conflict_reason": "<string or null>"
},
"linking": {
"primary_entity": "<string>",
"related_entities": ["<string>"]
},
"governance": {
"action": "STAGE_FOR_REVIEW" | "REJECT",
"reasoning": "<detailed explanation>"
}
}
Critical: The only valid governance actions are STAGE_FOR_REVIEW and REJECT. AUTO_APPROVE is deprecated and prohibited for organizational memory.
Final Status Mapping
let finalStatus = "pending_approval";
if (evaluation.governance.action === "REJECT") {
finalStatus = "rejected";
}
The agent returns a candidate and reasoning, not authority.
3. Triage Bot (knowledge)
File: services/knowledge/src/triage-bot.ts
Type: Function module (not an agent class)
Role: AI-powered knowledge extraction from conversations. Uses Workers AI for extraction, Slack for review notification.
Extraction Categories
| Category | Meaning |
|---|---|
| insight | Business insight or observation |
| fact | Concrete fact about customer, product, market |
| decision | Decision that was made |
| action_item | Task or follow-up committed to |
| preference | User or customer preference |
| relationship | Relationship between entities |
AI Provider Priority
- Cloudflare Workers AI (
env.AI) — edge-native, zero external calls - OpenRouter (
env.OPENROUTER_API_KEY) — fallback for larger models
What It Writes
triage_resultstable (Neon/D1) withapproval_status = 'pending'- Slack notification (review channel only, not authority bypass)
What It Never Writes
- Approved organizational memory
- Canonical entity state
- Direct promotions
Slack Integration
Slack is a review channel, not an authority bypass. A Slack reaction must become a verified approval event bound to the triage item, tenant, principal, and candidate version before promotion.
Reaction mapping:
- ✅ → Approve
- ❌ → Discard
- ⏰ → Defer