@elizaos/plugin-agent-orchestrator 2.0.0-alpha.9 → 2.0.3-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +60 -0
- package/LICENSE +21 -0
- package/README.md +232 -0
- package/docs/SUBAGENT_FLOW_AND_PARITY.md +138 -0
- package/docs/default-eliza-skills-and-agent-bridge-plan.md +225 -0
- package/docs/economics-goal-runbook.md +140 -0
- package/docs/multi-account-orchestration.md +76 -0
- package/docs/orchestrator-buildout-followups.md +124 -0
- package/docs/orchestrator-dashboard-task-widget-secrets-assessment.md +174 -0
- package/docs/orchestrator-dashboard-task-widget-secrets-design.md +301 -0
- package/docs/research/orchestrator-view-research-report.md +273 -0
- package/docs/sub-agent-routing.md +227 -0
- package/package.json +197 -38
- package/dist/index.d.ts +0 -21
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -21120
- package/dist/index.js.map +0 -109
- package/dist/src/actions/messaging.d.ts +0 -24
- package/dist/src/actions/messaging.d.ts.map +0 -1
- package/dist/src/actions/peek-subagent.d.ts +0 -3
- package/dist/src/actions/peek-subagent.d.ts.map +0 -1
- package/dist/src/actions/subagent-management.d.ts +0 -7
- package/dist/src/actions/subagent-management.d.ts.map +0 -1
- package/dist/src/actions/task-management.d.ts +0 -9
- package/dist/src/actions/task-management.d.ts.map +0 -1
- package/dist/src/config.d.ts +0 -4
- package/dist/src/config.d.ts.map +0 -1
- package/dist/src/providers/orchestrator-config.d.ts +0 -80
- package/dist/src/providers/orchestrator-config.d.ts.map +0 -1
- package/dist/src/providers/task-context.d.ts +0 -3
- package/dist/src/providers/task-context.d.ts.map +0 -1
- package/dist/src/services/agent-orchestrator-service.d.ts +0 -59
- package/dist/src/services/agent-orchestrator-service.d.ts.map +0 -1
- package/dist/src/services/messaging-service.d.ts +0 -111
- package/dist/src/services/messaging-service.d.ts.map +0 -1
- package/dist/src/services/sandbox-service.d.ts +0 -103
- package/dist/src/services/sandbox-service.d.ts.map +0 -1
- package/dist/src/services/subagent-service.d.ts +0 -140
- package/dist/src/services/subagent-service.d.ts.map +0 -1
- package/dist/src/sub-agents/adapter.d.ts +0 -13
- package/dist/src/sub-agents/adapter.d.ts.map +0 -1
- package/dist/src/sub-agents/claude-agent-sdk-sub-agent.d.ts +0 -18
- package/dist/src/sub-agents/claude-agent-sdk-sub-agent.d.ts.map +0 -1
- package/dist/src/sub-agents/codex-sdk-sub-agent.d.ts +0 -18
- package/dist/src/sub-agents/codex-sdk-sub-agent.d.ts.map +0 -1
- package/dist/src/sub-agents/eliza-sub-agent.d.ts +0 -27
- package/dist/src/sub-agents/eliza-sub-agent.d.ts.map +0 -1
- package/dist/src/sub-agents/elizaos-native-sub-agent.d.ts +0 -61
- package/dist/src/sub-agents/elizaos-native-sub-agent.d.ts.map +0 -1
- package/dist/src/sub-agents/index.d.ts +0 -10
- package/dist/src/sub-agents/index.d.ts.map +0 -1
- package/dist/src/sub-agents/opencode-sub-agent.d.ts +0 -44
- package/dist/src/sub-agents/opencode-sub-agent.d.ts.map +0 -1
- package/dist/src/sub-agents/registry.d.ts +0 -3
- package/dist/src/sub-agents/registry.d.ts.map +0 -1
- package/dist/src/sub-agents/sweagent-sub-agent.d.ts +0 -19
- package/dist/src/sub-agents/sweagent-sub-agent.d.ts.map +0 -1
- package/dist/src/sub-agents/tools.d.ts +0 -15
- package/dist/src/sub-agents/tools.d.ts.map +0 -1
- package/dist/src/sub-agents/types.d.ts +0 -170
- package/dist/src/sub-agents/types.d.ts.map +0 -1
- package/dist/src/types/index.d.ts +0 -12
- package/dist/src/types/index.d.ts.map +0 -1
- package/dist/src/types/messaging.d.ts +0 -202
- package/dist/src/types/messaging.d.ts.map +0 -1
- package/dist/src/types/sandbox.d.ts +0 -228
- package/dist/src/types/sandbox.d.ts.map +0 -1
- package/dist/src/types/subagent.d.ts +0 -232
- package/dist/src/types/subagent.d.ts.map +0 -1
- package/dist/src/types.d.ts +0 -138
- package/dist/src/types.d.ts.map +0 -1
- package/dist/src/utils/index.d.ts +0 -7
- package/dist/src/utils/index.d.ts.map +0 -1
- package/dist/src/utils/session.d.ts +0 -184
- package/dist/src/utils/session.d.ts.map +0 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.0 (unreleased)
|
|
4
|
+
|
|
5
|
+
ACP-based spawn, sub-agent routing, and workspace services into
|
|
6
|
+
a single package at `plugins/plugin-agent-orchestrator`. Internal
|
|
7
|
+
`@elizaos/plugin-acpx` callers were rewritten to the package.
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `SubAgentRouter` service: subscribes to `AcpService.onSessionEvent`,
|
|
12
|
+
posts terminal events (`task_complete`, `error`, `blocked`) as
|
|
13
|
+
synthetic inbound memories addressed to the original
|
|
14
|
+
`roomId`/`userId`/`messageId` captured at spawn time. Lets the main
|
|
15
|
+
agent's normal action layer decide `REPLY` / `SEND_TO_AGENT` / both.
|
|
16
|
+
- `activeSubAgentsProvider`: cache-stable view of routed sub-agent
|
|
17
|
+
sessions. Sorted by sessionId, structural-only fields, status bucketing
|
|
18
|
+
(`ready`/`running`/`busy`/`tool_running`/`authenticating` → `"active"`)
|
|
19
|
+
so transient flips don't invalidate the prefix cache.
|
|
20
|
+
- Round-trip cap: per-session inject counter; force-stops after
|
|
21
|
+
`ACPX_SUB_AGENT_ROUND_TRIP_CAP` (default 32) and surfaces a single
|
|
22
|
+
`round_trip_cap_exceeded` notice with `subAgentRoundTrip` /
|
|
23
|
+
`subAgentRoundTripCap` / `subAgentCapExceeded: true`.
|
|
24
|
+
- Live e2e test (`__tests__/live/sub-agent-router.live.test.ts`) gated on
|
|
25
|
+
`RUN_LIVE_ACPX=1` plus `acpx --version`.
|
|
26
|
+
- `spawnAgentAction` now threads `source: content.source` into spawn
|
|
27
|
+
metadata for parity with `createTaskAction`.
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- Package renamed from `@elizaos/plugin-acpx` → `@elizaos/plugin-agent-orchestrator`.
|
|
32
|
+
- `SubAgentRouter` derives the per-session sub-agent UUID locally via SHA1
|
|
33
|
+
instead of importing `createUniqueUuid` from `@elizaos/core`. This keeps
|
|
34
|
+
the router's import surface type-only.
|
|
35
|
+
- Browser build dropped: this package owns Node-only services
|
|
36
|
+
(`AcpService`, `CodingWorkspaceService`, child_process spawn).
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
|
|
40
|
+
- `task-agent-frameworks.ts` `normalizeTaskAgentAdapterForModelPrefs`:
|
|
41
|
+
removed three duplicate switch cases (`opencode` / `open-code` /
|
|
42
|
+
`open code`) that were dead code after the matching cases earlier in
|
|
43
|
+
the same switch.
|
|
44
|
+
- Greptile-flagged bugs from PR #7463 (already on develop pre-rename):
|
|
45
|
+
`"errored"` → `"error"` status normalization,
|
|
46
|
+
`listSessions`/`getSession` for FileSessionStore + RuntimeDbSessionStore,
|
|
47
|
+
`enforceSessionLimit` excluding both `"error"` and `"errored"`.
|
|
48
|
+
|
|
49
|
+
### Removed
|
|
50
|
+
|
|
51
|
+
- Removed the legacy swarm/terminal implementation family. The plugin now
|
|
52
|
+
has one task-agent transport: `AcpService` + `SubAgentRouter`.
|
|
53
|
+
|
|
54
|
+
## 0.1.0
|
|
55
|
+
|
|
56
|
+
Pre-consolidation. Bootstrap package scaffold for `@elizaos/plugin-acpx`
|
|
57
|
+
under its original name. Initial ACP subprocess service, session store
|
|
58
|
+
adapters, six canonical actions (`CREATE_TASK`, `SPAWN_AGENT`,
|
|
59
|
+
`SEND_TO_AGENT`, `STOP_AGENT`, `LIST_AGENTS`, `CANCEL_TASK`), and the
|
|
60
|
+
`availableAgentsProvider`.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 @stwd / 0xSolace
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# @elizaos/plugin-agent-orchestrator
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@elizaos/plugin-agent-orchestrator)
|
|
4
|
+
[](https://github.com/elizaos/eliza/actions/workflows/ci.yml)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
The canonical orchestration plugin for elizaOS task agents. Spawns local coding agents (elizaos, pi-agent, opencode, codex, claude) through Agent Client Protocol transports, routes their output back through the runtime so the main agent decides what to do, and bundles workspace lifecycle, GitHub PR integration, task share, and supporting services in a single package.
|
|
8
|
+
|
|
9
|
+
> Naming: this plugin is *not* the same thing as `@elizaos/plugin-acp`. That package is Shaw's ACP gateway client (IDE bridge over a remote ACP gateway). `@elizaos/plugin-agent-orchestrator` is the *task backend* that runs coding agents as subprocesses on the same host as the runtime.
|
|
10
|
+
|
|
11
|
+
## What it does
|
|
12
|
+
|
|
13
|
+
The plugin combines three concerns:
|
|
14
|
+
|
|
15
|
+
1. **Spawn** coding agents via ACP. The default path embeds ACP JSON-RPC session management in this plugin and talks directly to an ACP-compatible agent process; the legacy path can still shell out to [`acpx`](https://github.com/openclaw/acpx) when `ELIZA_ACP_TRANSPORT=cli`.
|
|
16
|
+
2. **Route** sub-agent terminal events (`task_complete`, `error`, `blocked`) and swarm coordination events back into the runtime as synthetic inbound messages addressed to the task room, worktree room, or original `roomId`/`userId`/`messageId`. The main agent's normal action layer then decides whether to `REPLY` to the user, `SEND_TO_AGENT` to push the sub-agent further, ask the task creator a question, or coordinate with other agents. See [`docs/sub-agent-routing.md`](./docs/sub-agent-routing.md).
|
|
17
|
+
3. **Coordinate** workspace lifecycle (clone, branch, commit, push, PR open) and GitHub issue management for repo-hosted tasks.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @elizaos/plugin-agent-orchestrator
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Native TypeScript ACP is the default transport. Set the default coding agent with `ELIZA_ACP_DEFAULT_AGENT` (`elizaos`, `pi-agent`, or `opencode` are the primary supported defaults):
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
export ELIZA_ACP_TRANSPORT=native
|
|
29
|
+
export ELIZA_ACP_DEFAULT_AGENT=elizaos
|
|
30
|
+
export ELIZA_ELIZAOS_ACP_COMMAND="elizaos"
|
|
31
|
+
export ELIZA_PI_AGENT_ACP_COMMAND="pi-agent"
|
|
32
|
+
export ELIZA_CODEX_ACP_COMMAND="npx -y @zed-industries/codex-acp@0.14.0"
|
|
33
|
+
export ELIZA_CLAUDE_ACP_COMMAND="npx -y @agentclientprotocol/claude-agent-acp@0.34.0"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Authenticate the underlying agent you plan to use before spawning sessions. Native Codex and Claude defaults use `npx`, so pin or replace those commands in production if you do not want runtime downloads.
|
|
37
|
+
|
|
38
|
+
The legacy command-wrapper path remains available for compatibility:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm install -g acpx@latest
|
|
42
|
+
export ELIZA_ACP_TRANSPORT=cli
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Adapter packaging decision: this release does not vendor the Codex or Claude ACP adapter packages. Native transport is the default; Codex and Claude use pinned `npx` commands unless deployment config overrides them. OpenCode is the exception: the package prefers the bundled OpenCode shim when available, then falls back to `opencode acp`.
|
|
46
|
+
|
|
47
|
+
`coding-agent-adapters` is a runtime registry/API dependency used by this plugin's agent inventory and routes; it is not a bundled Codex or Claude ACP adapter executable.
|
|
48
|
+
|
|
49
|
+
## Quick start
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import agentOrchestratorPlugin from "@elizaos/plugin-agent-orchestrator";
|
|
53
|
+
|
|
54
|
+
export default {
|
|
55
|
+
plugins: [agentOrchestratorPlugin],
|
|
56
|
+
};
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Action surface
|
|
60
|
+
|
|
61
|
+
All actions are virtual sub-operations of the single `TASKS` parent action, promoted via `promoteSubactionsToActions` with the `TASKS_` prefix.
|
|
62
|
+
|
|
63
|
+
| Promoted action | Sub-operation | Purpose |
|
|
64
|
+
| --- | --- | --- |
|
|
65
|
+
| `TASKS_CREATE` | `create` | One-shot: spawn + prompt + return. Captures origin metadata for routing. |
|
|
66
|
+
| `TASKS_SPAWN_AGENT` | `spawn_agent` | Start a long-lived ACP coding-agent session. Returns active session info. |
|
|
67
|
+
| `TASKS_SEND` | `send` | Send a follow-up prompt to a running session (`SEND_TO_AGENT` simile). |
|
|
68
|
+
| `TASKS_STOP_AGENT` | `stop_agent` | Cooperatively cancel + close a session. |
|
|
69
|
+
| `TASKS_LIST_AGENTS` | `list_agents` | List active and persisted sessions. |
|
|
70
|
+
| `TASKS_CANCEL` | `cancel` | Cancel an in-flight task while preserving history. |
|
|
71
|
+
| `TASKS_HISTORY` | `history` | Retrieve past task sessions. |
|
|
72
|
+
| `TASKS_CONTROL` | `control` | Lifecycle control: pause/resume/stop/continue/archive/reopen. |
|
|
73
|
+
| `TASKS_SHARE` | `share` | Share a task session. |
|
|
74
|
+
| `TASKS_PROVISION_WORKSPACE` | `provision_workspace` | Clone repo, create git worktree for a task. |
|
|
75
|
+
| `TASKS_SUBMIT_WORKSPACE` | `submit_workspace` | Commit, push, open PR for a workspace. |
|
|
76
|
+
| `TASKS_MANAGE_ISSUES` | `manage_issues` | GitHub issue create/list/get/update/comment/close/reopen/add_labels. |
|
|
77
|
+
| `TASKS_ARCHIVE` | `archive` | Archive a completed coding task. |
|
|
78
|
+
| `TASKS_REOPEN` | `reopen` | Reopen an archived task. |
|
|
79
|
+
|
|
80
|
+
## Providers
|
|
81
|
+
|
|
82
|
+
- `AVAILABLE_AGENTS` — adapter inventory + raw session list.
|
|
83
|
+
- `ACTIVE_SUB_AGENTS` — cache-stable view of currently-routed sub-agent sessions; sorted by sessionId, structural fields only (no timestamps, no message excerpts), so the planner-visible block stays cached across status flips.
|
|
84
|
+
- `ACTIVE_WORKSPACE_CONTEXT` — live workspace/session state.
|
|
85
|
+
- `CODING_AGENT_EXAMPLES` — structured action call examples.
|
|
86
|
+
- `CODING_SESSION_CHANGES` — real git changeset for "show me the diff" queries.
|
|
87
|
+
|
|
88
|
+
## Services
|
|
89
|
+
|
|
90
|
+
- `AcpService` — ACP subprocess lifecycle, session state, event emission, and transport selection. Registers under `ACP_SUBPROCESS_SERVICE`.
|
|
91
|
+
- `OrchestratorTaskService` — durable task store, sub-agent lifecycle API, event bridge from ACP to task records. Registers under `ORCHESTRATOR_TASK_SERVICE`.
|
|
92
|
+
- `SubAgentRouter` — subscribes to `AcpService.onSessionEvent`, posts terminal-event synthetic memories to `runtime.messageService.handleMessage`. Registers under `ACPX_SUB_AGENT_ROUTER`. Per-session round-trip cap (`ACPX_SUB_AGENT_ROUND_TRIP_CAP`, default 32) force-stops runaway loops. Disable with `ACPX_SUB_AGENT_ROUTER_DISABLED=1`.
|
|
93
|
+
- `CodingWorkspaceService` — git workspace lifecycle helpers. Registers under `CODING_WORKSPACE_SERVICE`.
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
import { AcpService, SubAgentRouter } from "@elizaos/plugin-agent-orchestrator";
|
|
97
|
+
|
|
98
|
+
const acp = runtime.getService("ACP_SUBPROCESS_SERVICE") as AcpService;
|
|
99
|
+
|
|
100
|
+
const { sessionId } = await acp.spawnSession({
|
|
101
|
+
agentType: "codex",
|
|
102
|
+
workdir: "/tmp/my-task",
|
|
103
|
+
approvalPreset: "permissive",
|
|
104
|
+
metadata: {
|
|
105
|
+
roomId: message.roomId,
|
|
106
|
+
userId: message.entityId,
|
|
107
|
+
messageId: message.id,
|
|
108
|
+
label: "fix bug 42",
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const result = await acp.sendPrompt(sessionId, "what is 7 + 8?");
|
|
113
|
+
console.log(result.finalText); // "15"
|
|
114
|
+
console.log(result.stopReason); // "end_turn"
|
|
115
|
+
console.log(result.durationMs); // 4864
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Subscribing to events
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
acp.onSessionEvent((sessionId, eventName, data) => {
|
|
122
|
+
// eventName: "ready" | "message" | "tool_running" | "task_complete" | "stopped" | "error" | "blocked" | "login_required" | "reconnected"
|
|
123
|
+
// data shape depends on eventName, see SessionEventName in src/services/types.ts
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The `task_complete` event:
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
{ response: string, durationMs: number, stopReason: "end_turn" | "error" | string }
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
You usually don't subscribe directly — `SubAgentRouter` already does, and routes terminal events into the runtime. Subscribe only if you need raw access (e.g. dashboards).
|
|
134
|
+
|
|
135
|
+
## Configuration
|
|
136
|
+
|
|
137
|
+
All configuration is via environment variables. Use `ELIZA_ACP_TRANSPORT=native` for the embedded TypeScript ACP client and `ELIZA_ACP_TRANSPORT=cli` only when you deliberately want the existing `acpx` wrapper.
|
|
138
|
+
|
|
139
|
+
| Variable | Default | Purpose |
|
|
140
|
+
| --- | --- | --- |
|
|
141
|
+
| `ELIZA_ACP_TRANSPORT` | `native` | Transport mode. Accepted values include `native`/`direct` and `cli`/`acpx`. |
|
|
142
|
+
| `ELIZA_ACP_CLI` | `acpx` | ACPX executable name or absolute path for the CLI transport. |
|
|
143
|
+
| `ELIZA_ACP_DEFAULT_AGENT` | `elizaos` | Default agent type. Primary choices: `elizaos`, `pi-agent`, `opencode`. |
|
|
144
|
+
| `ELIZA_ELIZAOS_ACP_COMMAND` | `elizaos` | Native elizaOS ACP command. |
|
|
145
|
+
| `ELIZA_PI_AGENT_ACP_COMMAND` | `pi-agent` | Native Pi Agent ACP command. |
|
|
146
|
+
| `ELIZA_CODEX_ACP_COMMAND` | `npx -y @zed-industries/codex-acp@0.14.0` | Native Codex ACP command. |
|
|
147
|
+
| `ELIZA_CLAUDE_ACP_COMMAND` | `npx -y @agentclientprotocol/claude-agent-acp@0.34.0` | Native Claude ACP command. |
|
|
148
|
+
| `ELIZA_OPENCODE_ACP_COMMAND` | bundled shim or `opencode acp` | Native OpenCode ACP command override. |
|
|
149
|
+
| `ELIZA_ACP_DEFAULT_APPROVAL` | `autonomous` | Approval preset (`read-only`, `auto`, `permissive`, `autonomous`, `full-access`). |
|
|
150
|
+
| `ELIZA_ACP_PROMPT_TIMEOUT_MS` / `ACPX_DEFAULT_TIMEOUT_MS` | `300000` (5m) | Per-prompt timeout. |
|
|
151
|
+
| `ELIZA_ACP_STATE_DIR` | `~/.eliza/plugin-acp` | Where to persist session state when no runtime DB. |
|
|
152
|
+
| `ACPX_DEFAULT_CWD` | runtime cwd | Base directory for spawned agent workdirs. |
|
|
153
|
+
| `ELIZA_ACP_MAX_SESSIONS` | `8` | Concurrent session cap. |
|
|
154
|
+
| `ACPX_SUB_AGENT_ROUTER_DISABLED` | unset | Set to `1` to keep the router service registered but unbound (test/staging). |
|
|
155
|
+
| `ACPX_SUB_AGENT_ROUND_TRIP_CAP` | `32` | Per-session inject cap before force-stop to prevent ping-pong loops. |
|
|
156
|
+
| `ACPX_PROGRESS_MODE` / `ELIZA_SUB_AGENT_PROGRESS_MODE` | `compact` | Sub-agent progress UX: `compact` delays and edits one status message, `threaded` preserves per-task threads, `silent` disables visible progress. |
|
|
157
|
+
| `ACPX_PROGRESS_DELAY_MS` / `ELIZA_SUB_AGENT_PROGRESS_DELAY_MS` | `15000` | Delay before the first visible progress message, so short tasks only show the final answer. |
|
|
158
|
+
| `ACPX_PROGRESS_REACTIONS` / `ELIZA_SUB_AGENT_PROGRESS_REACTIONS` | unset | Set to `1` to add progress reactions in `threaded` mode. |
|
|
159
|
+
|
|
160
|
+
### Native transport status
|
|
161
|
+
|
|
162
|
+
Native transport is an ACP JSON-RPC client. It currently handles `initialize`, `session/new`, `session/prompt`, cooperative `session/cancel`, `session/close`, file reads/writes scoped to the session workspace, permission requests, and basic terminal requests from the agent.
|
|
163
|
+
|
|
164
|
+
Use the CLI transport only when you need the existing `acpx` command wrapper semantics.
|
|
165
|
+
|
|
166
|
+
## Persistence
|
|
167
|
+
|
|
168
|
+
Session state is persisted with a tiered backend:
|
|
169
|
+
|
|
170
|
+
1. If `runtime.databaseAdapter` exposes SQL methods, sessions live in the `acp_sessions` table.
|
|
171
|
+
2. Otherwise, JSON file at `$ELIZA_ACP_STATE_DIR/sessions.json` (atomic writes via temp+rename).
|
|
172
|
+
3. Last resort: in-memory `Map` (warns that sessions won't survive restart).
|
|
173
|
+
|
|
174
|
+
## End-to-end smoke tests
|
|
175
|
+
|
|
176
|
+
Two smokes ship with the repo:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
# Raw AcpService against installed acpx + codex:
|
|
180
|
+
npm install -g acpx@latest
|
|
181
|
+
# authenticate codex first
|
|
182
|
+
npm run build
|
|
183
|
+
node tests/e2e/acp-codex-smoke.mjs
|
|
184
|
+
|
|
185
|
+
# Full router loop (vitest, gated):
|
|
186
|
+
RUN_LIVE_ACPX=1 bun run test
|
|
187
|
+
|
|
188
|
+
# Native ACP adapter smoke (gated, no-op unless enabled):
|
|
189
|
+
RUN_LIVE_NATIVE_ACP=1 node tests/e2e/live-native-acp-smoke.mjs
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
`acp-codex-smoke.mjs` exercises the legacy `acpx` path by spawning a real codex session, sending "what is 7 + 8?", and verifying `task_complete` fires with response `"15"`. The vitest live test (`__tests__/live/sub-agent-router.live.test.ts`) verifies the synthetic Memory routes back from a real subprocess into a test `messageService.handleMessage` with all routing keys intact. Both no-op (skip) when `acpx` isn't installed.
|
|
193
|
+
|
|
194
|
+
`live-native-acp-smoke.mjs` sets `ELIZA_ACP_TRANSPORT=native`, starts a native ACP adapter over stdio, sends a tiny math prompt, and verifies the prompt response ended with `stopReason: "end_turn"` and final text containing `15`. Optional providers require explicit commands:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
RUN_LIVE_NATIVE_ACP=1 LIVE_NATIVE_ACP_AGENT=claude ELIZA_CLAUDE_ACP_COMMAND="npx -y @agentclientprotocol/claude-agent-acp@0.34.0" node tests/e2e/live-native-acp-smoke.mjs
|
|
198
|
+
RUN_LIVE_NATIVE_ACP=1 LIVE_NATIVE_ACP_AGENT=opencode ELIZA_OPENCODE_ACP_COMMAND="opencode acp" node tests/e2e/live-native-acp-smoke.mjs
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
The native smoke skips successfully when `RUN_LIVE_NATIVE_ACP` is unset, when an optional provider command is not configured, or when the adapter reports missing authentication/credentials. Use `RUN_LIVE_NATIVE_ACP=1 bun run test -- __tests__/live/native-acp-smoke.live.test.ts` to run the same smoke through Vitest.
|
|
202
|
+
|
|
203
|
+
Native transport is covered by unit tests under `__tests__/unit/acp-native-transport.test.ts` and by the gated live smoke above.
|
|
204
|
+
|
|
205
|
+
## Package scripts
|
|
206
|
+
|
|
207
|
+
| Script | Purpose |
|
|
208
|
+
| --- | --- |
|
|
209
|
+
| `bun run build` / `bun run build:ts` | Build Node ESM, CJS, and declaration outputs. |
|
|
210
|
+
| `bun run dev` | Rebuild in watch mode. |
|
|
211
|
+
| `bun run typecheck` | Run TypeScript without emitting files. |
|
|
212
|
+
| `bun run test` | Run the plugin vitest suite. |
|
|
213
|
+
| `bun run test:unit` | Run unit tests only. |
|
|
214
|
+
| `bun run test:e2e:manual` | Run the manual `acp-codex-smoke.mjs` smoke against installed/authenticated `acpx` + Codex. |
|
|
215
|
+
| `bun run test:watch` | Run the vitest suite in watch mode. |
|
|
216
|
+
| `bun run lint:check` | Run Biome checks without writing changes. |
|
|
217
|
+
| `bun run lint` | Run Biome checks with write/unsafe fixes. |
|
|
218
|
+
| `bun run format:check` | Check formatting. |
|
|
219
|
+
| `bun run format` | Write formatting changes. |
|
|
220
|
+
| `bun run clean` | Remove local build/cache outputs. |
|
|
221
|
+
|
|
222
|
+
## Status
|
|
223
|
+
|
|
224
|
+
`2.0.3-beta.14` — package. ACP subprocess sessions are the only task-agent spawn path. The native ACP client is the default (`ELIZA_ACP_TRANSPORT=native`).
|
|
225
|
+
|
|
226
|
+
## Contributing
|
|
227
|
+
|
|
228
|
+
PRs welcome. Run `npm run typecheck && npm test` before opening.
|
|
229
|
+
|
|
230
|
+
## License
|
|
231
|
+
|
|
232
|
+
MIT. See [LICENSE](./LICENSE).
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Sub-agent flow & Codex / Claude-Code parity review
|
|
2
|
+
|
|
3
|
+
A thorough walk of how the main agent creates a task, spawns sub-agents,
|
|
4
|
+
provisions them, and communicates — across the elizaOS, Codex, and Claude
|
|
5
|
+
frameworks — plus an honest parity assessment against standalone Codex CLI and
|
|
6
|
+
Claude Code, and the concrete open items.
|
|
7
|
+
|
|
8
|
+
## 1. End-to-end flow
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
user msg → planner → TASKS_CREATE ─────────────► durable task (status: open)
|
|
12
|
+
│ roomId, taskRoomId, ownerUserId,
|
|
13
|
+
│ originalRequest, acceptanceCriteria
|
|
14
|
+
▼
|
|
15
|
+
TASKS_SPAWN_AGENT ────────────► AcpService.spawnSession(SpawnOptions)
|
|
16
|
+
│ goal-prompt.ts wraps agentType, workdir, goalPrompt,
|
|
17
|
+
│ the goal + rooms + approvalPreset, metadata{roomId,
|
|
18
|
+
│ acceptance criteria source, label, worldId, userId}
|
|
19
|
+
▼
|
|
20
|
+
ACP subprocess (native JSON-RPC over stdio)
|
|
21
|
+
elizaos | codex | claude | opencode | pi-agent
|
|
22
|
+
│ session/new → session/prompt(goal)
|
|
23
|
+
▼
|
|
24
|
+
events: ready · tool_running · message · reasoning · plan ·
|
|
25
|
+
blocked · task_complete · error · usage_update
|
|
26
|
+
│
|
|
27
|
+
┌────────────────┴───────────────────────────────┐
|
|
28
|
+
▼ ▼
|
|
29
|
+
OrchestratorTaskService.onSessionEvent SubAgentRouter.handleEvent
|
|
30
|
+
(durable: addEvent / updateSession / (synthetic Memory → planner;
|
|
31
|
+
recordMessage; task_complete → "validating") round-trip cap = 32)
|
|
32
|
+
│
|
|
33
|
+
▼
|
|
34
|
+
planner ↔ subAgentCompletionResponseEvaluator
|
|
35
|
+
→ reply to user OR TASKS_SEND_TO_AGENT
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Key files:** task create `actions/tasks.ts:685` → `services/orchestrator-task-service.ts:746`;
|
|
39
|
+
spawn `actions/tasks.ts:743` → `services/acp-service.ts:511`; goal wrap
|
|
40
|
+
`services/goal-prompt.ts:129`; event bridge `orchestrator-task-service.ts:519`;
|
|
41
|
+
routing `services/sub-agent-router.ts`; completion gate
|
|
42
|
+
`orchestrator-task-service.ts:608` (`task_complete` → `validating`, never straight
|
|
43
|
+
to `done`); evaluator `evaluators/sub-agent-completion.ts`.
|
|
44
|
+
|
|
45
|
+
**Provisioning** happens at spawn: `acp-service.ts` resolves the workdir, captures
|
|
46
|
+
a git baseline SHA + dirty set (for the completion changeset), and writes a
|
|
47
|
+
sub-agent `AGENTS.md`/`CLAUDE.md` identity manifest on bare workdirs
|
|
48
|
+
(`sub-agent-identity.ts`). Explicit repo clone / worktree / branch / commit / push
|
|
49
|
+
/ PR is `CodingWorkspaceService` (`workspace-*.ts`), driven by
|
|
50
|
+
`TASKS_PROVISION_WORKSPACE` / `TASKS_SUBMIT_WORKSPACE`.
|
|
51
|
+
|
|
52
|
+
## 2. Sub-agent rooms per task
|
|
53
|
+
|
|
54
|
+
- `roomId` = the originating user channel (where the final reply goes).
|
|
55
|
+
`taskRoomId` = a dedicated task-scoped room; all sessions' messages
|
|
56
|
+
(`senderKind: user|orchestrator|sub_agent|system`) append there. Exposed via
|
|
57
|
+
`GET /api/orchestrator/tasks/:id/messages`, `/timeline`, and `/stream` (SSE).
|
|
58
|
+
- The in-app **task view** (`plugin-task-coordinator/src/OrchestratorWorkbench.tsx`)
|
|
59
|
+
renders this as a per-task message room: the merged timeline + per-sub-agent
|
|
60
|
+
sessions list + plan + diff + usage + recovery, with near-live polling.
|
|
61
|
+
- On chat connectors, the **progress thread** (`index.ts emitProgress`) routes all
|
|
62
|
+
sub-agent narration into a per-task Discord thread / Telegram forum topic
|
|
63
|
+
(capability-gated on `create_thread` + `post_to_thread` + threaded progress
|
|
64
|
+
mode), keeping the main channel clean. This is the "task info as threads in TG
|
|
65
|
+
and Discord" surface.
|
|
66
|
+
|
|
67
|
+
## 3. Inter-agent communication
|
|
68
|
+
|
|
69
|
+
**Topology: hub-and-spoke.** Sub-agents do not address each other directly. Each
|
|
70
|
+
talks only to the parent:
|
|
71
|
+
- parent → sub: initial goal prompt; mid-flight `TASKS_SEND_TO_AGENT`; live user
|
|
72
|
+
messages in the task room are auto-forwarded to the active session
|
|
73
|
+
(`index.ts` MESSAGE_RECEIVED listener).
|
|
74
|
+
- sub → parent: terminal ACP events → synthetic memories; plus a sub-agent can
|
|
75
|
+
emit `USE_SKILL parent-agent {…}` which the router dispatches to the
|
|
76
|
+
parent-agent broker (`parent-agent-dispatch.ts` / `parent-agent-broker.ts`) and
|
|
77
|
+
replies back over the session.
|
|
78
|
+
- sub → parent context: loopback-only bridge `GET /api/coding-agents/:id/context/*`
|
|
79
|
+
(parent character, current room, memory search, active workspaces).
|
|
80
|
+
|
|
81
|
+
Multiple sub-agents per task are supported (`sessions[]`), unsynchronized; the
|
|
82
|
+
router de-dupes concurrent `task_complete` so only the first posts to the user.
|
|
83
|
+
|
|
84
|
+
## 4. Framework matrix (elizaOS / Codex / Claude)
|
|
85
|
+
|
|
86
|
+
All run as ACP subprocesses over the native JSON-RPC transport
|
|
87
|
+
(`acp-native-transport.ts`); spawn command per framework is env-overridable
|
|
88
|
+
(`ELIZA_{ELIZAOS,CODEX,CLAUDE,OPENCODE,PI_AGENT}_ACP_COMMAND`; Codex/Claude default
|
|
89
|
+
to pinned `npx` ACP shims). The orchestrator implements the ACP client side of:
|
|
90
|
+
`session/new`, `session/prompt`, `session/cancel`, `session/update` (streaming
|
|
91
|
+
`agent_message_chunk` / `agent_thought_chunk` / `tool_call` / `plan`),
|
|
92
|
+
`session/request_permission`, `fs/read_text_file`, `fs/write_text_file`, and the
|
|
93
|
+
`terminal/*` family. Approval presets (`readonly|standard|permissive|autonomous`)
|
|
94
|
+
gate file/terminal ops. Credentials reach sub-agents via the loopback credential
|
|
95
|
+
tunnel (`bridge-routes.ts`); host connector tokens are denylisted from the child
|
|
96
|
+
env, and Claude OAuth-subscription tokens are stripped so the child uses its own
|
|
97
|
+
subscription.
|
|
98
|
+
|
|
99
|
+
## 5. Parity vs standalone Codex CLI / Claude Code
|
|
100
|
+
|
|
101
|
+
**At parity:** multi-framework spawn + routing; file read/write; terminal exec;
|
|
102
|
+
plan/reasoning/tool streaming; approval gates; real git-diff capture & surfacing
|
|
103
|
+
(`coding-session-changes.ts`); token usage; orphaned-session recovery on restart;
|
|
104
|
+
durable task store + task view; per-task threads on connectors.
|
|
105
|
+
|
|
106
|
+
**Partial:** plan/todo events are emitted by OpenCode but not uniformly by
|
|
107
|
+
Codex/Claude; diff surfacing truncates (20 files / 50 lines) with no inline
|
|
108
|
+
per-line review UI; sub-agents run `--no-terminal` (event-driven, no interactive
|
|
109
|
+
TUI — correct for orchestration, but differs from a human at the CLI).
|
|
110
|
+
|
|
111
|
+
**Gaps:**
|
|
112
|
+
1. **MCP forwarding** — ✅ implemented (opt-in). `acp-native-transport.ts`
|
|
113
|
+
forwards `ELIZA_ACP_MCP_SERVERS` (a JSON array of stdio/http MCP server
|
|
114
|
+
configs) into `session/new.mcpServers` via `parseAcpMcpServersEnv`, so
|
|
115
|
+
sub-agents get the parent's MCP tools (Codex / Claude-Code parity). Defaults
|
|
116
|
+
to `[]` (prior behavior) so spawning never regresses. Remaining: auto-inherit
|
|
117
|
+
the parent runtime's MCP set without explicit env config (needs a runtime
|
|
118
|
+
MCP-config surface, which doesn't exist yet).
|
|
119
|
+
2. **Sub-agent nesting** (open) — no spawn-child API; a sub-agent cannot delegate
|
|
120
|
+
to its own sub-agents (single level of orchestration). Feature-level work.
|
|
121
|
+
3. **Inline code-review surface** — diffs are captured but there's no structured
|
|
122
|
+
per-file/line review/approve UI in the task view.
|
|
123
|
+
|
|
124
|
+
## 6. Open items checklist
|
|
125
|
+
|
|
126
|
+
- [x] Interaction protocol (forms / choice + custom / secret / task) across app + TG + Discord
|
|
127
|
+
- [x] Pick-an-option round-trip on both connectors; secret/OAuth DM link-out on both
|
|
128
|
+
- [x] Per-task threads on TG + Discord (orchestrator-driven; both connectors now capable)
|
|
129
|
+
- [x] Task view with sub-agent message room (OrchestratorWorkbench)
|
|
130
|
+
- [x] Real interaction-widget + connector round-trip tests
|
|
131
|
+
- [x] MCP server forwarding to sub-agents (opt-in via `ELIZA_ACP_MCP_SERVERS`)
|
|
132
|
+
- [ ] Sub-agent nesting / delegation (gap #2 — feature-level)
|
|
133
|
+
- [ ] Inline diff review UI in the task view (gap #3)
|
|
134
|
+
- [ ] Live connector E2E (needs TG/Discord credentials) + orchestrator HTTP task-flow E2E
|
|
135
|
+
- [ ] Optional: `outgoing_before_deliver` central interaction normalization hook
|
|
136
|
+
|
|
137
|
+
See `@elizaos/core` `src/messaging/interactions/README.md` for the interaction
|
|
138
|
+
protocol; this doc covers the orchestration + sub-agent layer.
|