II.
Page JSON
Structured · livepage:docs-adapters-babysitter-integrations-tasks-adapter-routing
Tasks-Adapter as Unified Task Routing Hub json
Inspect the normalized record payload exactly as the atlas UI reads it.
{
"id": "page:docs-adapters-babysitter-integrations-tasks-adapter-routing",
"_kind": "Page",
"_file": "wiki/docs/adapters-babysitter-integrations/tasks-adapter-routing.md",
"_cluster": "wiki",
"attributes": {
"nodeKind": "Page",
"sourcePath": "docs/adapters-babysitter-integrations/tasks-adapter-routing.md",
"sourceKind": "repo-docs",
"title": "Tasks-Adapter as Unified Task Routing Hub",
"displayName": "Tasks-Adapter as Unified Task Routing Hub",
"slug": "docs/adapters-babysitter-integrations/tasks-adapter-routing",
"articlePath": "wiki/docs/adapters-babysitter-integrations/tasks-adapter-routing.md",
"article": "\n# Tasks-Adapter as Unified Task Routing Hub\n\n## Motivation\n\nInstead of the SDK talking to adapters directly, **tasks-adapter** becomes the single routing layer for all task dispatch — human responders, adapters adapters, and external issue trackers. The SDK only needs to know about tasks-adapter.\n\nThis is better because:\n- One routing system for all task types (human, agent, external)\n- Cross-cutting concerns (priorities, dependencies, tracking, SLA) apply uniformly\n- tasks-adapter already has backend abstraction, responder matching, lifecycle management\n- Adapters becomes a \"responder type\" in tasks-adapter, not a separate integration surface\n- External issue trackers are also responder types — same abstraction\n\n## Architecture\n\n```\nSDK process: ctx.task(myTask)\n ↓ creates effect (journaled)\n ↓\ntasks-adapter routes by responder type:\n ├─ type: \"internal\" → agent-core session (direct API call)\n ├─ type: \"human\" → breakpoint → human responder (existing)\n ├─ type: \"agent\" → adapters adapter (claude-code, codex, etc.)\n ├─ type: \"tracker\" → external issue tracker (Jira, Linear, GitHub Issues)\n └─ type: \"auto\" → tasks-adapter picks best available responder\n```\n\n## Design Changes\n\n### 1. tasks-adapter: Responder Types\n\nCurrent responders are human-only. Extend to support agent responders:\n\n```typescript\n// packages/tasks-adapter/src/types.ts\n\ntype ResponderType = \"human\" | \"agent\" | \"tracker\" | \"internal\";\n\ninterface Responder {\n id: string;\n type: ResponderType;\n name: string;\n capabilities: string[];\n // Agent-specific:\n adapter?: string; // adapters adapter name\n model?: string; // default model\n provider?: string; // default provider\n // Tracker-specific:\n trackerBackend?: string; // \"github-issues\" | \"jira\" | \"linear\"\n trackerConfig?: Record<string, unknown>;\n}\n```\n\n### 2. tasks-adapter: Agent Responder Backend\n\nNew backend that wraps adapters:\n\n```typescript\n// packages/tasks-adapter/src/backends/adapters.ts\n\nclass AgentMuxResponderBackend implements BreakpointBackend {\n async submitBreakpoint(params: SubmitBreakpointParams): Promise<Breakpoint> {\n // Route to adapters adapter\n const adapterClient = await getAmuxClient();\n const handle = await adapterClient.run({\n agent: params.routing.targetAdapter,\n prompt: params.question,\n model: params.routing.model,\n nonInteractive: true,\n timeout: params.routing.timeout ?? 300_000,\n });\n \n // Collect result\n const result = await handle.result;\n \n // Return as answered breakpoint\n return {\n ...breakpoint,\n status: \"answered\",\n answer: { text: result.output, responderId: params.routing.targetAdapter },\n };\n }\n \n // waitForAnswer is immediate — agent responds synchronously\n async waitForAnswer(id: string): Promise<BreakpointAnswer> {\n return this.answers.get(id)!;\n }\n}\n```\n\n### 3. SDK: Task Definition Routes Through tasks-adapter\n\nReplace direct adapters references with tasks-adapter routing:\n\n```javascript\n// Process definition — routes through tasks-adapter\nconst reviewTask = defineTask(\"review\", (args) => ({\n kind: \"agent\",\n title: \"Code review\",\n agent: {\n prompt: \"Review the changes...\",\n // Routing handled by tasks-adapter, not SDK:\n responderType: \"agent\", // tasks-adapter routes to adapters\n adapter: \"claude-code\", // hint for tasks-adapter routing\n fallbackType: \"internal\", // if adapters unavailable, use internal\n },\n}));\n\n// Human review task — same routing system\nconst approvalTask = defineTask(\"approval\", (args) => ({\n kind: \"breakpoint\",\n title: \"Approve deployment\",\n breakpoint: {\n question: \"Approve deployment to production?\",\n responderType: \"human\", // tasks-adapter routes to human\n // Or sync to external tracker:\n responderType: \"tracker\",\n trackerBackend: \"jira\",\n },\n}));\n\n// Auto-routing — tasks-adapter picks best responder\nconst flexibleTask = defineTask(\"flexible\", (args) => ({\n kind: \"agent\",\n title: \"Implement feature\",\n agent: {\n prompt: \"Implement the feature...\",\n responderType: \"auto\", // tasks-adapter picks based on availability + capabilities\n },\n}));\n```\n\n### 4. tasks-adapter: Routing Logic\n\n```typescript\n// packages/tasks-adapter/src/router.ts\n\nasync function routeTask(task: TaskDef, context: RoutingContext): Promise<Responder> {\n const type = task.agent?.responderType ?? task.breakpoint?.responderType ?? \"internal\";\n \n switch (type) {\n case \"internal\":\n return { id: \"agent-core\", type: \"internal\", name: \"Internal Agent\", capabilities: [\"text\"] };\n \n case \"human\":\n return await matchHumanResponder(task, context);\n \n case \"agent\":\n return await matchAgentResponder(task, context);\n \n case \"tracker\":\n return await matchTrackerResponder(task, context);\n \n case \"auto\":\n // Try agent first (faster), fall back to human if no agent available\n const agent = await matchAgentResponder(task, context).catch(() => null);\n if (agent) return agent;\n return await matchHumanResponder(task, context);\n \n default:\n throw new Error(`Unknown responder type: ${type}`);\n }\n}\n\nasync function matchAgentResponder(task: TaskDef, context: RoutingContext): Promise<Responder> {\n const discovery = await discoverExternalAgents();\n if (!discovery.available) {\n if (task.agent?.fallbackType === \"internal\") {\n return { id: \"agent-core\", type: \"internal\", name: \"Internal (fallback)\", capabilities: [\"text\"] };\n }\n throw new Error(\"No agent responders available (adapters not installed)\");\n }\n \n const preferred = task.agent?.adapter;\n if (preferred) {\n const agent = discovery.agents.find(a => a.name === preferred && a.installed);\n if (agent) return { id: agent.name, type: \"agent\", name: agent.displayName, adapter: agent.name, capabilities: agent.capabilities };\n // Preferred not available — try any installed agent\n }\n \n const installed = discovery.agents.filter(a => a.installed && a.authenticated);\n if (installed.length === 0) throw new Error(\"No authenticated agent responders available\");\n return { id: installed[0].name, type: \"agent\", name: installed[0].displayName, adapter: installed[0].name, capabilities: installed[0].capabilities };\n}\n```\n\n### 5. Effect Resolution via tasks-adapter\n\nInstead of the current direct dispatch, effects flow through tasks-adapter:\n\n```\nCurrent:\n SDK effect → agent-platform resolveEffect → adapterBridge (direct)\n\nNew:\n SDK effect → tasks-adapter.submitTask(effect) → tasks-adapter.routeTask()\n → type=agent → AgentMuxResponderBackend → adapterBridge\n → type=human → BreakpointBackend (existing)\n → type=tracker → ExternalTrackerBackend (new)\n → type=internal → agent-core session (existing)\n```\n\n### 6. Plugin Mode Integration\n\nIn plugin mode (babysitter running inside claude-code), tasks-adapter routing is the same:\n- Internal tasks → delegated to host agent (via stop-hook)\n- Agent tasks → resolved internally by tasks-adapter → adapters → external agent\n- Human tasks → routed to tasks-adapter breakpoint system\n- Tracker tasks → synced to external tracker\n\nThe stop-hook handler queries tasks-adapter for task routing before deciding what to delegate to the host vs. resolve internally.\n\n## Benefits Over Direct Integration\n\n| Concern | Direct adapters | Through tasks-adapter |\n|---------|-----------------|-------------------|\n| Task priorities | Not supported | Built-in (when added to tasks-adapter) |\n| Dependencies | Not supported | Built-in (when added) |\n| SLA tracking | Not supported | Unified metrics across all responder types |\n| Retry/escalation | Manual | tasks-adapter handles escalation chains |\n| Audit trail | Per-dispatch | Unified breakpoint lifecycle |\n| Cost tracking | Per-dispatch | Aggregated across all tasks |\n| Human fallback | Custom code | `responderType: \"auto\"` handles it |\n| External tracking | Separate integration | Same backend abstraction |\n\n## Migration Path\n\n1. **Phase 1:** Add agent responder type to tasks-adapter + AgentMuxResponderBackend\n2. **Phase 2:** SDK routes through tasks-adapter instead of direct adapters\n3. **Phase 3:** Add tracker responder type for external issue trackers\n4. **Phase 4:** Add \"auto\" routing with capability-based responder matching\n5. **Phase 5:** Add priorities, dependencies, SLA across all responder types\n\n## Files to Create\n\n| File | Description |\n|------|-------------|\n| `packages/tasks-adapter/src/backends/adapters.ts` | Adapters responder backend |\n| `packages/tasks-adapter/src/router.ts` | Task routing logic |\n| `packages/tasks-adapter/src/responders/types.ts` | Extended responder types |\n| `packages/tasks-adapter/src/backends/__tests__/adapters.test.ts` | Tests |\n\n## Files to Modify\n\n| File | Change |\n|------|--------|\n| `packages/tasks-adapter/src/types.ts` | Add ResponderType, extend Responder |\n| `packages/tasks-adapter/src/backend.ts` | Support multiple backend types |\n| `packages/babysitter-sdk/src/runtime/intrinsics/task.ts` | Route through tasks-adapter |\n| `packages/genty/platform/src/harness/internal/createRun/orchestration/effects.ts` | Use tasks-adapter routing |\n| `packages/babysitter-sdk/src/harness/hooks/stopHookHandler.ts` | Query tasks-adapter for routing decisions |\n",
"documents": []
},
"outgoingEdges": [],
"incomingEdges": [
{
"from": "page:docs-adapters-babysitter-integrations",
"to": "page:docs-adapters-babysitter-integrations-tasks-adapter-routing",
"kind": "contains_page"
}
]
}