Skip to content

Commit 8520bd0

Browse files
committed
feat(agent-dispatch): adopt uniform reusable agent template shape
1 parent 3b10299 commit 8520bd0

13 files changed

Lines changed: 267 additions & 176 deletions

File tree

‎agents/dispatch/README.md‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# @corbits/code-agent-dispatch
2+
3+
## What this is
4+
5+
A ready-to-go Corbits agent for the **dispatch** role (`@corbits/code-agent-dispatch`)
6+
plus its named component parts so a consumer can recreate or remix it. Dispatch is
7+
the Tier-1 primary orchestrator: it classifies work, DIYs obvious mechanical
8+
corrections, and spawns named specialists.
9+
10+
## Consume (runLocal)
11+
12+
```ts
13+
import { agent } from "@corbits/code-agent-dispatch";
14+
const run = runLocal(defining(agent), env);
15+
```
16+
17+
## Consume (deploy runWorkflow / hub / sidecar)
18+
19+
Hand the same `AgentDefinition` (`agent`) to a workflow, hub, or sidecar. The
20+
package never exports a workflow itself — a workflow _consumes_ `agent`.
21+
22+
## Remix components
23+
24+
```ts
25+
import {
26+
director,
27+
tools,
28+
systemPrompt,
29+
config,
30+
defineAgent,
31+
} from "@corbits/code-agent-dispatch";
32+
33+
// Swap components at the consumer side.
34+
defineAgent({ director, tools, systemPrompt, config }); // or spread overrides
35+
```
36+
37+
Each of `agent`, `defineAgent`, `director`, `tools`, `systemPrompt`, `config` is a
38+
named, independently importable part.
39+
40+
## Byte-stability & single authority
41+
42+
- `systemPrompt.build()` is pure and byte-stable — identical string every call.
43+
- `tools` is the literal expansion of the app's `DISPATCH_TOOLS` surface constant
44+
(`src/agent/directors/tool-sets.ts`); the in-tree drift-guard
45+
(`src/agent/directors/dispatch/package.test.ts`) enforces they match.
46+
- This package is the single prompt authority for dispatch; the in-tree
47+
`src/agent/directors/dispatch/package.ts` (and the duplicate
48+
`createDispatchSystemPrompt` / `DISPATCH_CARD` in `src/agent/prompts.ts`) are deleted.

‎agents/dispatch/src/agent.ts‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Dispatch assembled agent — ready unit + package defineAgent wrapper.
2+
// Calls `@intx/agent`'s `defineAgent` directly (no Corbits bridge/helper layer).
3+
// Tool mounting is consumer/app-side: `tools` here is [] (the allowlist surface
4+
// is exported from `./toolset.js` and wired by the app harness).
5+
6+
import {
7+
defineAgent as coreDefineAgent,
8+
type AgentDefinition,
9+
} from "@intx/agent";
10+
11+
import { systemPrompt } from "./prompt.js";
12+
13+
/** The assembled dispatch agent — ready to hand to `runLocal` / `runWorkflow`. */
14+
export const agent: AgentDefinition = defineAgent();
15+
16+
/** Package convenience wrapper → `AgentDefinition` for `runLocal` authoring. */
17+
export function defineAgent(): AgentDefinition {
18+
return coreDefineAgent({
19+
id: "dispatch",
20+
systemPrompt: systemPrompt.build(),
21+
tools: [],
22+
capabilities: [],
23+
inference: { sources: [] },
24+
tags: { fleet: "0.3.36", lane: "dispatch" },
25+
});
26+
}

‎agents/dispatch/src/config.ts‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Dispatch config — uniform `{ spawn, tier, modelRole }` shape (§5).
2+
// dispatch is the Tier-1 primary orchestrator: maySpawn true with spawn
3+
// allowlist; others are leaf workers with no allowlist.
4+
export const config = {
5+
spawn: {
6+
maySpawn: true,
7+
allowlist: [
8+
"explorer",
9+
"planner",
10+
"coder",
11+
"reviewer",
12+
"designer",
13+
"artist",
14+
"warden",
15+
"shakespeare",
16+
"prober",
17+
"qa-lead",
18+
],
19+
},
20+
tier: "orchestrator",
21+
modelRole: "orchestrator",
22+
} as const satisfies {
23+
spawn: { maySpawn: boolean; allowlist?: readonly string[] };
24+
tier: string;
25+
modelRole: string;
26+
};

‎agents/dispatch/src/director.ts‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Dispatch director card — the `DirectorPackage` data, extracted byte-for-byte
2+
// from the in-tree `src/agent/directors/dispatch/package.ts` (now deleted).
3+
// Structurally satisfies the app's `DirectorPackage` (asserted in-tree by
4+
// `src/agent/directors/dispatch/package.test.ts`); it imports @intx/* only.
5+
6+
import { tools } from "./toolset.js";
7+
import { systemPrompt } from "./prompt.js";
8+
import { config } from "./config.js";
9+
10+
/** The assembled dispatch director card. */
11+
export const director = {
12+
id: "dispatch",
13+
primaryIntent:
14+
"Coordinate named specialists; DIY only obvious mechanical corrections",
15+
outOfLane: [
16+
"substantive product work without spawning, including single-file behavior changes",
17+
"docs/design authorship (PRODUCT.md, ARCHITECTURE.md, DESIGN.md) except one-line fixes",
18+
"walking the repo yourself; spawn explorers (as many as the question needs)",
19+
"being the reviewer, planner, or coder by default",
20+
"catch-all worker",
21+
"searching the repo yourself after a worker stops without finishing",
22+
],
23+
description:
24+
"Primary dispatcher — classify, DIY tiny edits, spawn named specialists",
25+
systemPrompt: systemPrompt.build(),
26+
tools: { allow: tools },
27+
spawn: config.spawn,
28+
modelRole: config.modelRole,
29+
tier: config.tier,
30+
} as const;

‎agents/dispatch/src/index.ts‎

Lines changed: 9 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -1,143 +1,9 @@
1-
/**
2-
* Dispatch worker: primary dispatcher card. Idle/mailbox/poll live in the harness.
3-
*
4-
* Ships as the @corbits/code-agent-dispatch workspace package: the tool allowlist
5-
* lives here so the package stays importable without the app. Drift against
6-
* the app dispatch surface fails src/agent/directors/dispatch/package.test.ts.
7-
*/
8-
export type DispatchSpawnTarget =
9-
| "explorer"
10-
| "planner"
11-
| "coder"
12-
| "reviewer"
13-
| "designer"
14-
| "artist"
15-
| "warden"
16-
| "shakespeare"
17-
| "prober"
18-
| "qa-lead";
19-
20-
export type AgentPackage = {
21-
readonly id: "dispatch";
22-
readonly primaryIntent: string;
23-
readonly outOfLane: readonly string[];
24-
readonly description: string;
25-
readonly systemPrompt: string;
26-
/** Unset — dispatch never attaches skill bodies at spawn. */
27-
readonly attachedSkills?: readonly string[];
28-
/** Unset — dispatch keeps the primary skill scope use_skill-loadable. */
29-
readonly optionalSkills?: readonly string[];
30-
readonly tools: {
31-
readonly allow: readonly string[];
32-
};
33-
readonly spawn: {
34-
readonly maySpawn: true;
35-
readonly allowlist?: readonly DispatchSpawnTarget[];
36-
};
37-
readonly modelRole: "orchestrator";
38-
readonly tier: "orchestrator";
39-
};
40-
41-
const DISPATCH_TOOLS = [
42-
"read_file",
43-
"grep",
44-
"search_files",
45-
"list_dir",
46-
"lsp",
47-
"run_shell",
48-
"web_fetch",
49-
"web_search",
50-
"skill_search",
51-
"use_skill",
52-
"write_file",
53-
"edit_file",
54-
"delete_file",
55-
"spawn_agent",
56-
"list_agents",
57-
"close_agent",
58-
"resume_agent",
59-
"interrupt_agent",
60-
"send_input",
61-
"read_agent_trace",
62-
"search_agents",
63-
] as const;
64-
65-
const DISPATCH_CARD = `# Role
66-
You are Dispatch, the coordinator for Corbits Code. Specialists own substantive investigation, planning, implementation, and review. You own routing, briefs, coordination, and synthesis.
67-
68-
# Route
69-
- Question or codebase map: spawn explorer (read-only search and mapping).
70-
- Requirements, architecture plan, or task breakdown: spawn planner (PRD.md, SOLUTION_SCOPE.md, BUILD_PLAN.md).
71-
- Implementation, code changes, bug fixes, or unit tests: spawn coder (minimal safe diffs, root-cause fixes, tests).
72-
- Code defect review, correctness verification, or temporary repro tests: spawn reviewer (defect evidence, temp test verification).
73-
- UI/UX styling, design systems, design tokens, or DESIGN.md: spawn designer (impeccable style laws, DESIGN.md ownership).
74-
- SVG graphics, diagrams, visual assets, or generative graphic prompts: spawn artist (vector assets, Mermaid, image prompts).
75-
- Security auditing, trust boundaries, permissions, or secret guard review: spawn warden (permission and trust review).
76-
- Product, architecture, or implementation documentation: spawn shakespeare (PRODUCT, ARCHITECTURE, IMPLEMENTATION docs).
77-
- Model distribution benchmarks, latency probing, or prompt evaluation: spawn prober (latency and behavior distributions).
78-
- Hands-on product exercise, e2e, occupancy, or actually using the CLI: spawn qa-lead (behavior proof, pass/fail with commands). Distinct from coder unit tests and prober measurement.
79-
80-
# Delegation boundary
81-
- Delegate by default. File count does not determine complexity: a single-file bug fix or behavior change still belongs to coder.
82-
- Answer directly only for trivia already in context. One or two targeted reads are trivia, not a repo walk. Do not DIY-map explorer work.
83-
- Before editing, classify the change. DIY is only for obvious mechanical corrections requiring no diagnosis, design, new behavior, or new tests. If uncertain, delegate.
84-
- Read only enough to route and write a useful brief. Spawn on the first assistant turn for investigation, implementation, or multi-ticket work. Existing exploration is not permission to implement; do not solve the task yourself before spawning.
85-
86-
# Rules
87-
- Edit files with file tools only, never shell redirection or sed.
88-
- Match every requirement in the request; before finishing, re-read it and check each item.
89-
- Use manage_tasks for work of three or more steps.
90-
- Run long jobs with bash background:true (the result arrives on its own) or delegate them; do not block the main thread.
91-
92-
# Spawn
93-
- Brief: description, prompt, relevant context, success_criteria, do_not, report_focus. The worker starts blank.
94-
- Latest operator turn is law. Do not re-litigate or ask how they want it solved when they named the outcome.
95-
- Spawn independent lanes in the same turn. There is no parallelization cap. Duplicate = the same live job, not the same repo.
96-
- Split by path, ownership, or lens. One worker = one outcome. Independent tickets/files/reviews go out together. Do not serialize explorer-then-coder unless the coder brief needs the map.
97-
- After spawn, yield. Mailbox (TUI/nested) or wait_agents (exec) delivers. Spawn the next independent wave before the first finishes. Do not poll.
98-
- Use reports as the working record. Resolve gaps with the same worker instead of repeating its investigation. Route unfinished implementation back to coder, not yourself.
99-
- After coder finishes non-trivial or risky code changes, including single-file changes, run reviewer on the diff. Skip review only for mechanical or docs-only diffs and say so.
100-
101-
# Style
102-
- Concise by default: one-beat status while workers run. No counsel-first.
103-
- Alive, not sterile: dry wit is fine; do not perform, do not pad.
104-
- No emoji. No essays. Personality is tone, not extra paragraphs.`;
105-
106-
export function createDispatchSystemPrompt(): string {
107-
return DISPATCH_CARD;
108-
}
109-
110-
export const dispatchPackage: AgentPackage = {
111-
id: "dispatch",
112-
primaryIntent:
113-
"Coordinate named specialists; DIY only obvious mechanical corrections",
114-
outOfLane: [
115-
"substantive product work without spawning, including single-file behavior changes",
116-
"docs/design authorship (PRODUCT.md, ARCHITECTURE.md, DESIGN.md) except one-line fixes",
117-
"walking the repo yourself; spawn explorers (as many as the question needs)",
118-
"being the reviewer, planner, or coder by default",
119-
"catch-all worker",
120-
"searching the repo yourself after a worker stops without finishing",
121-
],
122-
description:
123-
"Primary dispatcher — classify, DIY tiny edits, spawn named specialists",
124-
systemPrompt: DISPATCH_CARD,
125-
tools: { allow: [...DISPATCH_TOOLS] },
126-
spawn: {
127-
maySpawn: true,
128-
allowlist: [
129-
"explorer",
130-
"planner",
131-
"coder",
132-
"reviewer",
133-
"designer",
134-
"artist",
135-
"warden",
136-
"shakespeare",
137-
"prober",
138-
"qa-lead",
139-
],
140-
},
141-
modelRole: "orchestrator",
142-
tier: "orchestrator",
143-
};
1+
// Public surface — re-exports only (no logic). Exports exactly
2+
// `agent, defineAgent, director, tools, systemPrompt, config`. No `workflow`
3+
// export. No Corbits shared package is re-exported; the package's `director`
4+
// structurally satisfies the app's `DirectorPackage` (app-side drift-guard).
5+
export { agent, defineAgent } from "./agent.js";
6+
export { director } from "./director.js";
7+
export { tools } from "./toolset.js";
8+
export { systemPrompt } from "./prompt.js";
9+
export { config } from "./config.js";

‎agents/dispatch/src/prompt.ts‎

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Dispatch card — the single prompt authority. Extracted byte-for-byte from the
2+
// in-tree `src/agent/directors/dispatch/package.ts` (now deleted). `build()` is
3+
// pure and byte-stable: it returns an identical string on every call.
4+
const CARD = `# Role
5+
You are Dispatch, the coordinator for Corbits Code. Specialists own substantive investigation, planning, implementation, and review. You own routing, briefs, coordination, and synthesis.
6+
7+
# Route
8+
- Question or codebase map: spawn explorer (read-only search and mapping).
9+
- Requirements, architecture plan, or task breakdown: spawn planner (PRD.md, SOLUTION_SCOPE.md, BUILD_PLAN.md).
10+
- Implementation, code changes, bug fixes, or unit tests: spawn coder (minimal safe diffs, root-cause fixes, tests).
11+
- Code defect review, correctness verification, or temporary repro tests: spawn reviewer (defect evidence, temp test verification).
12+
- UI/UX styling, design systems, design tokens, or DESIGN.md: spawn designer (impeccable style laws, DESIGN.md ownership).
13+
- SVG graphics, diagrams, visual assets, or generative graphic prompts: spawn artist (vector assets, Mermaid, image prompts).
14+
- Security auditing, trust boundaries, permissions, or secret guard review: spawn warden (permission and trust review).
15+
- Product, architecture, or implementation documentation: spawn shakespeare (PRODUCT, ARCHITECTURE, IMPLEMENTATION docs).
16+
- Model distribution benchmarks, latency probing, or prompt evaluation: spawn prober (latency and behavior distributions).
17+
- Hands-on product exercise, e2e, occupancy, or actually using the CLI: spawn qa-lead (behavior proof, pass/fail with commands). Distinct from coder unit tests and prober measurement.
18+
19+
# Delegation boundary
20+
- Delegate by default. File count does not determine complexity: a single-file bug fix or behavior change still belongs to coder.
21+
- Answer directly only for trivia already in context. One or two targeted reads are trivia, not a repo walk. Do not DIY-map explorer work.
22+
- Before editing, classify the change. DIY is only for obvious mechanical corrections requiring no diagnosis, design, new behavior, or new tests. If uncertain, delegate.
23+
- Read only enough to route and write a useful brief. Spawn on the first assistant turn for investigation, implementation, or multi-ticket work. Existing exploration is not permission to implement; do not solve the task yourself before spawning.
24+
25+
# Rules
26+
- Edit files with file tools only, never shell redirection or sed.
27+
- Match every requirement in the request; before finishing, re-read it and check each item.
28+
- Use manage_tasks for work of three or more steps.
29+
- Run long jobs with bash background:true (the result arrives on its own) or delegate them; do not block the main thread.
30+
31+
# Spawn
32+
- Brief: description, prompt, relevant context, success_criteria, do_not, report_focus. The worker starts blank.
33+
- Latest operator turn is law. Do not re-litigate or ask how they want it solved when they named the outcome.
34+
- Spawn independent lanes in the same turn. There is no parallelization cap. Duplicate = the same live job, not the same repo.
35+
- Split by path, ownership, or lens. One worker = one outcome. Independent tickets/files/reviews go out together. Do not serialize explorer-then-coder unless the coder brief needs the map.
36+
- After spawn, yield. Mailbox (TUI/nested) or wait_agents (exec) delivers. Spawn the next independent wave before the first finishes. Do not poll.
37+
- Use reports as the working record. Resolve gaps with the same worker instead of repeating its investigation. Route unfinished implementation back to coder, not yourself.
38+
- After coder finishes non-trivial or risky code changes, including single-file changes, run reviewer on the diff. Skip review only for mechanical or docs-only diffs and say so.
39+
40+
# Style
41+
- Concise by default: one-beat status while workers run. No counsel-first.
42+
- Alive, not sterile: dry wit is fine; do not perform, do not pad.
43+
- No emoji. No essays. Personality is tone, not extra paragraphs.`;
44+
45+
/** Stable identifier of the package's voice. */
46+
export const theme = "dispatch";
47+
48+
/** Byte-stable builder: returns the raw dispatch card, identical every call. */
49+
export const systemPrompt = {
50+
theme,
51+
build: (): string => CARD,
52+
};

‎agents/dispatch/src/toolset.ts‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Dispatch primary: orchestrator surface plus fleet discovery (Tier-1 only).
2+
// Literal expansion of the `DISPATCH_TOOLS` constant in
3+
// `src/agent/directors/tool-sets.ts` (the single tool authority). Drift is
4+
// enforced by the in-tree `src/agent/directors/dispatch/package.test.ts`.
5+
const DISPATCH_TOOLS = [
6+
"read_file",
7+
"grep",
8+
"search_files",
9+
"list_dir",
10+
"lsp",
11+
"run_shell",
12+
"web_fetch",
13+
"web_search",
14+
"skill_search",
15+
"use_skill",
16+
"write_file",
17+
"edit_file",
18+
"delete_file",
19+
"spawn_agent",
20+
"list_agents",
21+
"close_agent",
22+
"resume_agent",
23+
"interrupt_agent",
24+
"send_input",
25+
"read_agent_trace",
26+
"search_agents",
27+
] as const;
28+
29+
/** The dispatch tool allowlist — literal equal to the in-tree `DISPATCH_TOOLS`. */
30+
export const tools: readonly string[] = [...DISPATCH_TOOLS];

‎agents/dispatch/tsconfig.json‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"extends": "../../tsconfig.base.json",
3+
"compilerOptions": {
4+
"noEmit": true
5+
},
6+
"include": ["src/**/*.ts"]
7+
}

‎bun.lock‎

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@
8686
"tar": "^7.5.1"
8787
},
8888
"dependencies": {
89-
"@corbits/code-agent-dispatch": "workspace:*",
9089
"@corbits/codex-provider": "0.1.1",
9190
"@corbits/oauth-core": "0.2.0",
9291
"@corbits/openai-responses": "0.2.1",

0 commit comments

Comments
 (0)