@polygraph/opencode-plugin 0.4.48 → 0.4.49
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/README.md +34 -11
- package/agent-session-link.mjs +6 -3
- package/agents/polygraph-delegate-subagent.md +27 -130
- package/package.json +1 -1
- package/skills/await-polygraph-ci/SKILL.md +5 -5
- package/skills/polygraph/SKILL.md +23 -81
- package/skills/polygraph/reference/delegation.md +105 -0
- package/skills/session-start/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<h1 align="center">Polygraph Skills</h1>
|
|
9
9
|
|
|
10
10
|
<p align="center">
|
|
11
|
-
AI agent skills and subagents for <a href="https://trypolygraph.com/">Polygraph</a> — the meta-harness for maximum agentic autonomy, giving agents visibility across every repo and memory that survives every session.
|
|
11
|
+
AI agent skills and subagents for <a href="https://trypolygraph.com/">Polygraph</a> — the agent-agnostic meta-harness for maximum agentic autonomy, giving agents visibility across every repo and memory that survives every session.
|
|
12
12
|
</p>
|
|
13
13
|
|
|
14
14
|
<p align="center">
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
## What is Polygraph?
|
|
25
25
|
|
|
26
|
-
Polygraph is
|
|
26
|
+
Polygraph is the agent-agnostic meta-harness for maximum agentic autonomy. It works with the agents you already use and gives them what they're missing: visibility across every repo boundary, and memory that survives every session. Agents discover how repositories relate, coordinate changes across them, and hand off or resume work later with repos, branches, PRs, and logs all preserved.
|
|
27
27
|
|
|
28
28
|
## Setup
|
|
29
29
|
|
|
@@ -35,19 +35,42 @@ polygraph config
|
|
|
35
35
|
|
|
36
36
|
It detects your AI agent — Claude Code, Codex, OpenCode, and more — and installs the Polygraph skills and subagents for it. Re-run it any time to add another agent or update an existing install.
|
|
37
37
|
|
|
38
|
+
### Codex: raising the long-poll ceiling
|
|
39
|
+
|
|
40
|
+
The delegate subagent polls child agents with `show_agent(waitForTransitionMs: 300000)` — a single 5-minute wait instead of a stream of short polls, which is what keeps delegation cheap. Claude Code and OpenCode honor the full wait. Codex does not by default.
|
|
41
|
+
|
|
42
|
+
Codex caps every MCP tool call at `tool_timeout_sec = 60`, so long polls effectively cap at 50s. Nothing the plugin ships can change that: a plugin's `.mcp.json` has no timeout field, and `tool_timeout_sec` is only read from `~/.codex/config.toml`. Polling still works at 50s — the MCP resolves the real ceiling per client and returns early rather than erroring — you just pay for more round trips.
|
|
43
|
+
|
|
44
|
+
To get the full 5-minute wait under Codex, set **both**:
|
|
45
|
+
|
|
46
|
+
1. `tool_timeout_sec` in `~/.codex/config.toml`:
|
|
47
|
+
|
|
48
|
+
```toml
|
|
49
|
+
[mcp_servers.polygraph]
|
|
50
|
+
tool_timeout_sec = 360
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
2. `POLYGRAPH_MCP_MAX_WAIT_MS` in that server's env, if you launch it from the CLI:
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
POLYGRAPH_MCP_MAX_WAIT_MS=300000
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Neither is required — they are a throughput optimization, not a correctness fix.
|
|
60
|
+
|
|
38
61
|
## Skills
|
|
39
62
|
|
|
40
|
-
- **polygraph** — Comprehensive guidance for Polygraph sessions: shared context, repository graph visibility, PR/CI state, delegation, and session management
|
|
41
|
-
- **adversarial-review** — Second-opinion review of a session's work by independent reviewer agents, one per repo, running under a read-only `reviewer` role
|
|
42
|
-
- **await-polygraph-ci** — Wait for CI pipelines to settle across all repos in a session, investigate failures, and present fix options
|
|
43
|
-
- **get-latest-ci** — One-shot fetch of the latest CI pipeline execution for the current branch
|
|
44
|
-
- **session-debrief** — Analyze the raw logs of past Polygraph sessions and produce structured, rank-ordered debriefs for use in a different session
|
|
63
|
+
- **polygraph** — Comprehensive guidance for Polygraph sessions: shared context, repository graph visibility, PR/CI state, delegation, and session management.
|
|
64
|
+
- **adversarial-review** — Second-opinion review of a session's work by independent reviewer agents, one per repo, running under a read-only `reviewer` role.
|
|
65
|
+
- **await-polygraph-ci** — Wait for CI pipelines to settle across all repos in a session, investigate failures, and present fix options.
|
|
66
|
+
- **get-latest-ci** — One-shot fetch of the latest CI pipeline execution for the current branch.
|
|
67
|
+
- **session-debrief** — Analyze the raw logs of past Polygraph sessions and produce structured, rank-ordered debriefs for use in a different session.
|
|
45
68
|
|
|
46
69
|
## Agents
|
|
47
70
|
|
|
48
|
-
- **polygraph-init-subagent** — Discovers candidate repositories and initializes a Polygraph session
|
|
49
|
-
- **polygraph-delegate-subagent** — Delegates work to a child agent in another repository, polls for completion
|
|
50
|
-
- **session-debrief** — Analyzes the raw logs of past Polygraph sessions and returns a structured, rank-ordered debrief for the current task
|
|
71
|
+
- **polygraph-init-subagent** — Discovers candidate repositories and initializes a Polygraph session.
|
|
72
|
+
- **polygraph-delegate-subagent** — Delegates work to a child agent in another repository, polls for completion.
|
|
73
|
+
- **session-debrief** — Analyzes the raw logs of past Polygraph sessions and returns a structured, rank-ordered debrief for the current task.
|
|
51
74
|
|
|
52
75
|
## Development
|
|
53
76
|
|
|
@@ -71,7 +94,7 @@ For the strictest release flow, do not allow direct `npm publish` for the truste
|
|
|
71
94
|
|
|
72
95
|
## Learn More
|
|
73
96
|
|
|
74
|
-
- **[Polygraph](https://trypolygraph.com/)** — The meta-harness for maximum agentic autonomy
|
|
97
|
+
- **[Polygraph](https://trypolygraph.com/)** — The agent-agnostic meta-harness for maximum agentic autonomy
|
|
75
98
|
- **[@polygraph/mcp](https://www.npmjs.com/package/@polygraph/mcp)** — The MCP server that powers Polygraph tools
|
|
76
99
|
## License
|
|
77
100
|
|
package/agent-session-link.mjs
CHANGED
|
@@ -157,13 +157,13 @@ function createOpenCodeSessionLinker({
|
|
|
157
157
|
if (root) roots.set(sessionId, root);
|
|
158
158
|
return root;
|
|
159
159
|
}
|
|
160
|
-
async function submit(openCodeSessionId, cwd, polygraphSessionId) {
|
|
160
|
+
async function submit(openCodeSessionId, cwd, polygraphSessionId, lifecycle = false) {
|
|
161
161
|
if (!openCodeSessionId || env && Object.hasOwn(env, "POLYGRAPH_CHILD_AGENT")) {
|
|
162
162
|
return false;
|
|
163
163
|
}
|
|
164
164
|
const agentSessionId = await rootSessionId(openCodeSessionId);
|
|
165
165
|
if (!agentSessionId) return false;
|
|
166
|
-
const lifecycleKey = polygraphSessionId ? `${polygraphSessionId}\0${agentSessionId}` : void 0;
|
|
166
|
+
const lifecycleKey = polygraphSessionId ? `${polygraphSessionId}\0${agentSessionId}` : lifecycle ? `\0${agentSessionId}` : void 0;
|
|
167
167
|
if (lifecycleKey && linkedLifecycleSessions.has(lifecycleKey)) return false;
|
|
168
168
|
const linked = await submitLink({
|
|
169
169
|
...polygraphSessionId ? { polygraphSessionId } : {},
|
|
@@ -184,7 +184,10 @@ function createOpenCodeSessionLinker({
|
|
|
184
184
|
async fromSessionCreated(info) {
|
|
185
185
|
if (!info?.id || info.parentID) return false;
|
|
186
186
|
roots.set(info.id, info.id);
|
|
187
|
-
|
|
187
|
+
if (env.POLYGRAPH_SESSION_ID) {
|
|
188
|
+
return fromEnvironment(info.id, info.directory);
|
|
189
|
+
}
|
|
190
|
+
return submit(info.id, info.directory, void 0, true);
|
|
188
191
|
},
|
|
189
192
|
fromEnvironment,
|
|
190
193
|
async fromToolActivity(input) {
|
|
@@ -1,157 +1,54 @@
|
|
|
1
1
|
---
|
|
2
2
|
|
|
3
|
-
description:
|
|
3
|
+
description: Waits for one Polygraph child agent (addressed by delegation id) to finish or need attention, then exits with a short fixed message. Never reads logs. Runs in the background.
|
|
4
4
|
mode: subagent
|
|
5
5
|
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Polygraph Delegate Subagent
|
|
9
9
|
|
|
10
|
-
You
|
|
10
|
+
You wait for one Polygraph child agent to finish. You do not read its work.
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
The main agent already spawned the child via `spawn_agent` and received a delegation id. Your entire job is to poll that id until the child needs attention, then exit with a short fixed message. The main agent reads the child's result itself — every log line you echo is duplicated tokens, so you never fetch logs.
|
|
13
13
|
|
|
14
|
-
## Input
|
|
14
|
+
## Input (from the main agent)
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
| Parameter | Description |
|
|
17
|
+
| ----------- | ------------------------------------------------------------ |
|
|
18
|
+
| `sessionId` | The Polygraph session ID |
|
|
19
|
+
| `id` | The delegation id returned by `spawn_agent` (e.g. `frontend-1`) |
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
| ------------- | ---------------------------------------------------------------------------- |
|
|
20
|
-
| `sessionId` | The Polygraph session ID |
|
|
21
|
-
| `repo` | Repository to delegate to (e.g., `org/repo-name`) |
|
|
22
|
-
| `instruction` | The task instruction for the child agent |
|
|
23
|
-
| `role` | (Optional) Agent slot within the repo; omit for the default role and never invent one. Pass the SAME role on every `spawn_agent`/`show_agent`/`stop_agent` call for this delegation. |
|
|
24
|
-
| `context` | (Optional) Additional context to pass to the child agent |
|
|
21
|
+
## Loop
|
|
25
22
|
|
|
26
|
-
|
|
23
|
+
Call the `show_agent` tool with exactly these arguments, repeatedly:
|
|
27
24
|
|
|
28
|
-
|
|
25
|
+
- `sessionId`: the session ID
|
|
26
|
+
- `id`: the delegation id
|
|
27
|
+
- `waitForTransitionMs`: 300000
|
|
29
28
|
|
|
30
|
-
`
|
|
29
|
+
Never pass `tail`. Never call any other tool. Never read files, transcripts, or logs.
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
Each call blocks up to 5 minutes, then returns the child's `status` on `children[0]`:
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
sessionId: "<sessionId>",
|
|
37
|
-
repo: "<repo>",
|
|
38
|
-
instruction: "<instruction>",
|
|
39
|
-
role: "<role, if any>",
|
|
40
|
-
context: "<context>"
|
|
41
|
-
)
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
The call returns immediately — the child agent runs asynchronously.
|
|
45
|
-
|
|
46
|
-
**Polling with long-poll waits:**
|
|
47
|
-
|
|
48
|
-
Call `show_agent` in a loop, passing `waitForTransitionMs: 50000` on every call:
|
|
49
|
-
|
|
50
|
-
```
|
|
51
|
-
show_agent(
|
|
52
|
-
sessionId: "<sessionId>",
|
|
53
|
-
repo: "<repo>",
|
|
54
|
-
role: "<role, if any>",
|
|
55
|
-
waitForTransitionMs: 50000
|
|
56
|
-
)
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
Each call blocks up to ~50 seconds and resolves within ~1 second of a state change. It returns immediately if the child is already terminal, `input-required`, or `permission-required`. Call it back-to-back in a loop.
|
|
33
|
+
- `in-progress` or `created` → call `show_agent` again with the same arguments.
|
|
34
|
+
- `completed`, `failed`, `cancelled`, `input-required`, or `permission-required` → stop looping and exit with the message below.
|
|
60
35
|
|
|
61
|
-
|
|
36
|
+
If a call errors, retry it once. If it errors again, exit with the error text plus the delegation id and stop.
|
|
62
37
|
|
|
63
|
-
|
|
38
|
+
## Exit message (fixed template)
|
|
64
39
|
|
|
65
|
-
|
|
66
|
-
{ "taskId": "…", "message": "…", "status": "delegated" }
|
|
67
|
-
```
|
|
40
|
+
Return exactly this, filled in from the last `show_agent` response — nothing more:
|
|
68
41
|
|
|
69
|
-
Then poll `show_agent` in a loop with `waitForTransitionMs: 50000`. **Do not pass a `tail` argument** — the tool's default is sized for status polling. Only set `tail` if you have a specific reason (e.g., the default truncated output you actually need to inspect, or you are hunting for an earlier failure that scrolled off). Never ratchet `tail` upward across polls; that is what causes the polling loop to flood your context window.
|
|
70
|
-
|
|
71
|
-
The response's `children[]` array has one entry per agent matching your query. Find YOUR delegation's entry (match on `role`; absent means the default role) and inspect:
|
|
72
|
-
|
|
73
|
-
- `child.status` — an AcpRunStatus value: one of `'created'`, `'in-progress'`, `'input-required'`, `'permission-required'`, `'completed'`, `'failed'`, `'cancelled'` (British double-L on `'cancelled'`). Note `'permission-required'` and `'input-required'` are DIFFERENT states handled by different cases below — do not conflate them.
|
|
74
|
-
- `child.inputRequiredQuestion` — populated only when `child.status === 'input-required'`; contains the verbatim question the child agent has asked the parent.
|
|
75
|
-
- `child.lastOutputLines` — recent log tail (use for status narration; do not treat as an API surface).
|
|
76
|
-
- `child.repoFullName` — human-facing identifier for which repo is talking.
|
|
77
|
-
|
|
78
|
-
State machine:
|
|
79
|
-
|
|
80
|
-
1. `child.status === 'created'` or `'in-progress'` — child is still executing. Call `show_agent` (with `waitForTransitionMs: 50000`) again.
|
|
81
|
-
2. `child.status === 'input-required'` — child is paused waiting for parent input:
|
|
82
|
-
- Read `child.inputRequiredQuestion`.
|
|
83
|
-
- Surface this question verbatim to the parent/user: "The child agent in `{child.repoFullName}` needs input: {child.inputRequiredQuestion}".
|
|
84
|
-
- Wait for the parent/user to supply an answer.
|
|
85
|
-
- Call `spawn_agent` again with the same `repo`, the same `role`, and `instruction: <the answer>` — the orchestrator routes it to that (repo, role)'s active task automatically.
|
|
86
|
-
- Resume polling.
|
|
87
|
-
|
|
88
|
-
3. `child.status === 'permission-required'` — child is paused waiting for a permission grant decision:
|
|
89
|
-
- Read `child.pendingPermission` — inspect `harness`, `action`, `target`, `repoFullName`, `scope`, `availableScopes`, and optional `reason`/`rawInput`.
|
|
90
|
-
- Surface the request to the parent/user: "Child agent in `{repoFullName}` requests `{scope}` permission to run `{action}` on `{target}`."
|
|
91
|
-
- Wait for the parent/user to decide.
|
|
92
|
-
- Call `allow_agent` (to grant) or `deny_agent` (to refuse) with `{ sessionId, repo, role? }` — `allow_agent` also takes `scope` (`'one-time'` or `'session'`) and an optional `reason`; `deny_agent` takes only an optional `reason` on top.
|
|
93
|
-
- **Fail-closed:** When you see `permission-required`, you MUST call either `allow_agent` or `deny_agent`. Failing to call one leaves the gate held open until the child's idle timer fires; the child cannot make progress until you decide.
|
|
94
|
-
- Resume polling.
|
|
95
|
-
|
|
96
|
-
4. `child.status === 'completed'` — child finished successfully. Read `child.lastOutputLines` for the most recent log tail and report outcome.
|
|
97
|
-
5. `child.status === 'failed'` — child failed. Read `child.lastOutputLines` for failure context and report the error.
|
|
98
|
-
6. `child.status === 'cancelled'` — child was stopped via `stop_agent`. Its session is preserved for later context restoration. Do not restart or continue work from that preserved session unless the user explicitly asks for changes.
|
|
99
|
-
|
|
100
|
-
## Cancelling a running child
|
|
101
|
-
|
|
102
|
-
To cancel a running child mid-work, call `stop_agent` with the repo (and `role`, per the parameter rule above). Response:
|
|
103
|
-
|
|
104
|
-
```json
|
|
105
|
-
{
|
|
106
|
-
"taskId": "…",
|
|
107
|
-
"state": "cancelled",
|
|
108
|
-
"sessionPreserved": true,
|
|
109
|
-
"output": "…",
|
|
110
|
-
"message": "…"
|
|
111
|
-
}
|
|
112
42
|
```
|
|
43
|
+
Child agent <id> is done.
|
|
113
44
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
When the child agent reaches a terminal status, return a structured summary:
|
|
45
|
+
**Repo:** <repoFullName>
|
|
46
|
+
**Delegation id:** <id>
|
|
47
|
+
**Status:** <status>
|
|
119
48
|
|
|
49
|
+
Read the result with show_agent (id: "<id>").
|
|
120
50
|
```
|
|
121
|
-
## Polygraph Delegation Result
|
|
122
|
-
|
|
123
|
-
**Repo:** <repo>
|
|
124
|
-
**Role:** <role, or "default" when none was given>
|
|
125
|
-
**Status:** <success | failed | cancelled>
|
|
126
|
-
**Session ID:** <sessionId>
|
|
127
|
-
|
|
128
|
-
### Result
|
|
129
|
-
<result text drawn from child.lastOutputLines>
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
## Timeout
|
|
133
|
-
|
|
134
|
-
If polling exceeds **30 minutes**, return with a timeout status:
|
|
135
|
-
|
|
136
|
-
```
|
|
137
|
-
## Polygraph Delegation Result
|
|
138
|
-
|
|
139
|
-
**Repo:** <repo>
|
|
140
|
-
**Status:** timeout
|
|
141
|
-
**Session ID:** <sessionId>
|
|
142
|
-
**Elapsed:** <minutes>m
|
|
143
|
-
|
|
144
|
-
### Suggestions
|
|
145
|
-
- Check child agent status manually via `show_agent`
|
|
146
|
-
- Consider stopping the child agent via `stop_agent`
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
## Important Notes
|
|
150
51
|
|
|
151
|
-
-
|
|
52
|
+
For `input-required` or `permission-required`, replace "is done." with "needs attention." and keep everything else identical.
|
|
152
53
|
|
|
153
|
-
|
|
154
|
-
- Do NOT call `push_branch` or `create_pr` — those are the main agent's responsibility
|
|
155
|
-
- If `spawn_agent` fails, return the error immediately
|
|
156
|
-
- If `show_agent` returns an error, wait and retry (count as failed poll)
|
|
157
|
-
- After 5 consecutive poll failures, return with `status: error`
|
|
54
|
+
Do not summarize, quote, or describe the child's work. Do not include log lines. The main agent reads the result itself via `show_agent`.
|
package/package.json
CHANGED
|
@@ -157,15 +157,15 @@ For each repo with `ciStatus: FAILED`, branch on the PR's `ci` object from `show
|
|
|
157
157
|
|
|
158
158
|
Since `spawn_agent` is non-blocking, you can delegate to multiple failed repos in parallel.
|
|
159
159
|
|
|
160
|
-
3. **Monitor investigation progress** —
|
|
160
|
+
3. **Monitor investigation progress** — launch one background `polygraph-delegate-subagent` per delegation id and let it do the waiting. When it exits, read that investigation with a single unwaited `show_agent`:
|
|
161
161
|
|
|
162
162
|
```
|
|
163
|
-
show_agent(sessionId: "<session-id>",
|
|
163
|
+
show_agent(sessionId: "<session-id>", id: "<delegation-id>")
|
|
164
164
|
```
|
|
165
165
|
|
|
166
|
-
|
|
166
|
+
`result.text` is the child's investigation summary. Never run a waited `show_agent` loop here, and do not pass `tail` unless `result.text` alone is insufficient.
|
|
167
167
|
|
|
168
|
-
4. Collect each child agent's response from
|
|
168
|
+
4. Collect each child agent's response from its unwaited `show_agent` read. If a child agent fails or gets stuck, use `stop_agent` with its delegation id to terminate it and skip that repo.
|
|
169
169
|
|
|
170
170
|
5. Display failure summary for each repo:
|
|
171
171
|
|
|
@@ -202,5 +202,5 @@ For each repo with `ciStatus: FAILED`, branch on the PR's `ci` object from `show
|
|
|
202
202
|
- All heavy CI data inspection happens in child agents via `spawn_agent` to keep this context window clean.
|
|
203
203
|
|
|
204
204
|
- Child agents can use `get_ci_logs` to save CI job logs to local files, but ONLY when no CIPE exists for the PR (`pr.ci.cipeUrl` is null). When a CIPE exists, logs come from the CIPE system via the Nx MCP `ci_information` tool. Job IDs come from `pr.ci.externalCIRuns[].jobs[].jobId` in the `show_session` response. The tool returns a file path (`logFile`) and size (`sizeBytes`) — use the `Read` tool to examine the log content. Logs can be large (100KB+), so only fetch logs for failed or relevant jobs.
|
|
205
|
-
- `spawn_agent` is **non-blocking** — it starts the child agent and returns immediately.
|
|
205
|
+
- `spawn_agent` is **non-blocking** — it starts the child agent and returns a delegation id immediately. Waiting on that id belongs in a background poller subagent; an unwaited `show_agent` by id returns the result, and `stop_agent` by id terminates a stuck agent.
|
|
206
206
|
- The `show_session` response is compact and safe to poll from the main agent.
|
|
@@ -6,11 +6,11 @@ description: Guidance for working with Polygraph sessions, shared/resumable agen
|
|
|
6
6
|
|
|
7
7
|
# Working with Polygraph
|
|
8
8
|
|
|
9
|
-
**IMPORTANT:** Polygraph keeps local clones only for *other* repositories in the session. NEVER `cd` into those clones or access their files directly — work in other repositories ALWAYS happens through the Polygraph MCP `spawn_agent` tool,
|
|
9
|
+
**IMPORTANT:** Polygraph keeps local clones only for *other* repositories in the session. NEVER `cd` into those clones or access their files directly — work in other repositories ALWAYS happens through the Polygraph MCP `spawn_agent` tool. Before delegating anything, read [`reference/delegation.md`](reference/delegation.md).
|
|
10
10
|
|
|
11
11
|
Polygraph connects repos and the agent work happening across them. Its central artifact is the session, which groups the repos, branches, PRs, and CI status for one piece of work and can be shared and resumed: use it to coordinate changes across multiple repos or in a single repoto share the session URL with collaborators, hand off progress via the session description, resume prior work, and watch CI across the session's PRs.
|
|
12
12
|
|
|
13
|
-
**Polygraph operates on the current repo in place.** Starting
|
|
13
|
+
**Polygraph operates on the current repo in place.** Starting a session never clones or modifies the repository you are in — you keep working in your real working directory, and `push_branch` pushes your local commits from that checkout. Only *other* repos are worked on in separate Polygraph-managed clones via `spawn_agent`. Resuming is the one qualified case: a `resume_session` with the explicit `reset` consent force-switches branches inside the session's materialized repositories, and can force-move the current working tree when it is itself one of them. Repositories outside the session folder are never modified. Full contract under "Explore an Existing Session".
|
|
14
14
|
|
|
15
15
|
## Available Tools
|
|
16
16
|
|
|
@@ -20,9 +20,10 @@ Polygraph functionality is available via both MCP tools and CLI commands. Use wh
|
|
|
20
20
|
| --- | --- | --- |
|
|
21
21
|
| `list_repos` | `polygraph repo list` | Discover candidate repositories. Candidate entries do not include repository descriptions; use `semanticQuery` for natural-language discovery. |
|
|
22
22
|
| `start_session` | `polygraph session start --repo <ids>` | Initialize a Polygraph session with selected repositories |
|
|
23
|
-
| `
|
|
24
|
-
| `
|
|
25
|
-
| `
|
|
23
|
+
| `resume_session` | `polygraph session resume --session <id> --json` | Join an existing session from this conversation: a tracked adoption that performs the full reconstruct. On divergence it stays local by default; `reset` is an explicit, destructive opt-in. Divergence and post-join behavior are under "Explore an Existing Session". |
|
|
24
|
+
| `spawn_agent` | — | Start a child task, or send a follow-up to an active task, in another repository; returns a delegation id. A repeat call for the same (repo, role) is delivered to that task as a follow-up; otherwise a new child starts. See `reference/delegation.md`. |
|
|
25
|
+
| `show_agent` | — | Poll by repo or delegation id; unwaited reads return the child's result. Waited calls are for the poller subagent, not the main conversation. See `reference/delegation.md`. |
|
|
26
|
+
| `stop_agent` | — | Cancel an in-progress child by delegation id; its session is preserved for later read-only context restoration. |
|
|
26
27
|
| `push_branch` | — | Push a local git branch to the remote repository. For the repo you are in, this pushes from your current checkout. Requires a session description. |
|
|
27
28
|
| `create_pr` | — | Create draft PRs with session metadata linking related PRs |
|
|
28
29
|
| `show_session` | `polygraph session show <id> [--details]` | Query status of the current session. Use details when session summary, repo IDs, PR URLs, and PR descriptions are needed. |
|
|
@@ -42,7 +43,7 @@ Polygraph functionality is available via both MCP tools and CLI commands. Use wh
|
|
|
42
43
|
| `select_account` | `polygraph account select` | Select the organization that future commands run against |
|
|
43
44
|
| `whoami` | `polygraph whoami` | Show current auth status and org |
|
|
44
45
|
|
|
45
|
-
**Delegation rules:** `list_repos` and `start_session` MUST be called via the `polygraph-init-subagent` as described in the "Initialize or Join Polygraph Session" section. Direct `add_repo` is allowed only when the user provides exact repo refs for an existing session. `spawn_agent` and `show_agent`
|
|
46
|
+
**Delegation rules:** `list_repos` and `start_session` MUST be called via the `polygraph-init-subagent` as described in the "Initialize or Join Polygraph Session" section. Direct `add_repo` is allowed only when the user provides exact repo refs for an existing session. `spawn_agent` is a fast, non-blocking call and IS allowed directly in the main conversation — it returns a delegation id. Waited `show_agent` POLLING must run in a background `@polygraph-delegate-subagent`, never inline. One-off unwaited `show_agent` reads in the main conversation are fine and expected — that is how you read a child's result. See [`reference/delegation.md`](reference/delegation.md).
|
|
46
47
|
|
|
47
48
|
## CLI Statefulness
|
|
48
49
|
|
|
@@ -71,10 +72,10 @@ After logging in (or if logged in but no org is selected), use `polygraph accoun
|
|
|
71
72
|
The delegate/monitor/stop steps apply only when working across repos. A single-repo session skips them and still benefits from shared progress, resume, and CI visibility.
|
|
72
73
|
|
|
73
74
|
0. **Initialize or join Polygraph session** - If you were spawned inside an existing session (the startup banner names a session ID), reuse it. Call `show_session` first; if it already has repos and the user did not ask to add more, you're done. If the user asks to add exact repo refs, call `add_repo` directly and skip candidate discovery. If the session has no repos and no exact refs were provided, launch the `polygraph-init-subagent` with that `sessionId` so it discovers candidates and uses `add_repo` (NOT `start_session`). Only when there is no session ID at all should the init subagent create a new session.
|
|
74
|
-
1. **Delegate work to each repo** -
|
|
75
|
+
1. **Delegate work to each repo** - Call `spawn_agent` for each repo to get a delegation id, then launch one background `polygraph-delegate-subagent` per id to wait on it. With the default role, delegate only to *other* repos — never to the repo you are in; work on it directly (your regular subagents are fine for local work — only Polygraph delegation is reserved for other repos). Delegating into the repo you are in is allowed only with an explicit non-default `role`. Parallel delegation across repos is encouraged. Read [`reference/delegation.md`](reference/delegation.md) before delegating.
|
|
75
76
|
|
|
76
|
-
4. **Monitor child agents** -
|
|
77
|
-
5. **Stop child agents** (if needed) - Use `stop_agent`
|
|
77
|
+
4. **Monitor child agents** - Let the background poller subagent do the waiting. When it exits, read that child's answer with a single unwaited `show_agent(sessionId, id)` — `result.text` is the child's final message.
|
|
78
|
+
5. **Stop child agents** (if needed) - Use `stop_agent` with the delegation id to cancel an in-progress child agent. The agent's session is preserved for later read-only context restoration; after a resume, wait for explicit user instructions before making changes.
|
|
78
79
|
6. **Push branches** - Use `push_branch` after making commits. A required `description` must follow the Session Description Policy.
|
|
79
80
|
7. **Create draft PRs** - Use `create_pr` to create linked draft PRs. Always pass `description` following the Session Description Policy.
|
|
80
81
|
8. **Associate existing PRs** (optional) - Use `associate_pr` to link PRs created outside Polygraph.
|
|
@@ -90,6 +91,8 @@ There are three cases. Pick exactly one before calling any tool. The case labels
|
|
|
90
91
|
|
|
91
92
|
**Hard rule: if a session ID is already in scope (e.g., the startup banner says "You're in Polygraph session …", or the user passed one or you are provided one by a reminder hook), that session ID is authoritative for this entire conversation. NEVER call `start_session` — doing so creates a brand-new session and orphans the one the parent harness is pointed at. Reuse the existing session via `show_session` and, if needed, `add_repo`.**
|
|
92
93
|
|
|
94
|
+
**Hard rule: before doing ad-hoc work in another repository, or reading a session's context untracked, ask whether an existing session already covers this work. If one might and its session ID is not in scope, ask the user for it — never fall back to an ad-hoc clone. To WORK in a session's context, join it via `resume_session` — a tracked adoption. To only read or summarize, `show_session` remains the read path.**
|
|
95
|
+
|
|
93
96
|
**Case A — Existing session, already has repos.** Call `show_session` directly with the known session ID. Skip the init subagent entirely, show the session details (format below), and proceed.
|
|
94
97
|
|
|
95
98
|
**Case B — Existing session, no repos yet (or user wants to add more).** If the user gives exact repo refs by ID, short name, full name, GitHub `owner/repo` slug, or URL-like slug, call `add_repo(sessionId, repoIds: [...])` directly with those refs. Do NOT call `list_repos`, do NOT ask for candidates, and do NOT launch the init subagent just to resolve those refs. If the user wants discovery/filtering instead, launch the `polygraph-init-subagent`, passing both the existing `sessionId` and `userContext`. The subagent will discover candidates, select relevant repositories, and call `add_repo` against the existing session — it will NOT call `start_session`.
|
|
@@ -130,11 +133,11 @@ The subagent will:
|
|
|
130
133
|
|
|
131
134
|
Use this workflow when the user gives a Polygraph session ID and asks to understand, resume, inspect, or investigate prior work.
|
|
132
135
|
|
|
133
|
-
**Resume is not a work command.** If the user's intent is to resume, reconnect, or reconstruct a prior Polygraph session,
|
|
136
|
+
**Resume is not a work command.** If the user's intent is to resume, reconnect, or reconstruct a prior Polygraph session, join it via `resume_session`, summarize the restored context it returns, then stop. Do not edit files, push branches, add repos, delegate new work, or continue previous changes until the user explicitly asks for changes. Recording the join in the session's history is not making changes to the work. Treat "resume" as context restoration followed by waiting for user instructions.
|
|
134
137
|
|
|
135
|
-
1. Fetch
|
|
136
|
-
-
|
|
137
|
-
-
|
|
138
|
+
1. Fetch session context by intent:
|
|
139
|
+
- To continue work in the session from this conversation, join it via `resume_session` (CLI: `polygraph session resume --session <id> --json`) — a tracked adoption that performs the full reconstruct; the restored session context comes back in the tool result. On a divergent session the join stays on the local conversation by default and returns the divergence evidence; adopting the selected path requires the explicit `reset` consent, a destructive opt-in that force-switches branches in the session's materialized repositories (discarding uncommitted tracked changes there, untracked files survive) and deletes this machine's local session logs.
|
|
140
|
+
- To only read, inspect, or summarize without joining, prefer `show_session` with `details: true`; otherwise run `polygraph session show --details <session-id>`. This is the read-only path and records nothing.
|
|
138
141
|
2. Treat the detailed output as authoritative context. It should include:
|
|
139
142
|
- `<summary>` — the session summary.
|
|
140
143
|
- `<repositories>` — relevant repos, including each repo's `<id>` and `<name>`.
|
|
@@ -176,71 +179,9 @@ Inspect the PR commits/diff and investigate the requested behavior. Report findi
|
|
|
176
179
|
Use this workflow when the user asks which Polygraph session produced, is behind, or changed a particular commit — or a particular line of code.
|
|
177
180
|
**Read [`reference/session-by-commit.md`](reference/session-by-commit.md) before running any lookup.** That reference file holds clear, reliable steps for answering questions related to this.
|
|
178
181
|
|
|
179
|
-
##
|
|
180
|
-
|
|
181
|
-
A repository in a session can host multiple child agents at once, distinguished by **role**:
|
|
182
|
-
|
|
183
|
-
- **Omit by default.** Set a `role` only when the user very explicitly asked for a named one, or when a skill the user invoked prescribes one (e.g. `adversarial-review` uses `reviewer`). Never pick one yourself.
|
|
184
|
-
- **Purpose.** Roles let independent streams of work run concurrently in one repo — e.g. a default agent implementing a feature while a `reviewer` or `ci-investigator` runs alongside. Each (repo, role) pair has at most one active child.
|
|
185
|
-
- **Default role.** An omitted `role` means the default role: `spawn_agent` without `role` starts or follows up with the repo's default-role agent.
|
|
186
|
-
- **Logs.** Only default-role agents upload logs to the cloud and appear in the multiplexed log stream (`polygraph session logs`). Inspect non-default agents locally with `polygraph agent attach --role <role>`.
|
|
187
|
-
|
|
188
|
-
## Simple tasks (fire-and-forget)
|
|
189
|
-
|
|
190
|
-
Use this pattern when the task is well-defined and the child is not expected to need clarification. It is a single-round delegation: kick it off, poll until terminal, then push branch + create PR.
|
|
191
|
-
|
|
192
|
-
**CRITICAL:** `spawn_agent` and `show_agent` MUST ALWAYS be called via `@polygraph-delegate-subagent`, NEVER directly from the main conversation. Direct calls flood the context window with polling noise and degrade the user experience. This is a hard requirement, not a suggestion.
|
|
193
|
-
|
|
194
|
-
1. For each repo, invoke `@polygraph-delegate-subagent` with `sessionId`, `repo`, `instruction`, optional `role`, and optional `context`. The subagent calls `spawn_agent`, then polls `show_agent` via chained `waitForTransitionMs` long-poll calls until terminal.
|
|
195
|
-
2. Delegate to multiple repos in parallel by launching multiple `@polygraph-delegate-subagent` invocations — one delegation per (repo, role) at a time.
|
|
196
|
-
3. The subagent watches `child.status` on its delegation's `children[]` entry — the one matching its repo and role — and exits when it sees a terminal status — typically `'completed'` or `'failed'` (and `'cancelled'` if it was stopped).
|
|
197
|
-
4. Once all subagents report a terminal status, continue to `push_branch` + `create_pr`.
|
|
198
|
-
|
|
199
|
-
To debug a stuck subagent you can call `show_agent` as a one-off, but routine polling belongs in the background subagents.
|
|
200
|
-
|
|
201
|
-
Use Simple when the task is well-defined and the child will not need clarification.
|
|
202
|
-
|
|
203
|
-
## Multi-turn tasks (interactive)
|
|
204
|
-
|
|
205
|
-
Use this pattern when the child may need clarification, the task is exploratory, or interactive collaboration is desired. The orchestrator exposes paused children via the `'input-required'` status.
|
|
206
|
-
|
|
207
|
-
1. Call `spawn_agent` with the initial `instruction` (and optionally `role`). Parse the response:
|
|
208
|
-
|
|
209
|
-
```json
|
|
210
|
-
{ "taskId": "…", "message": "…", "status": "delegated" }
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
2. Poll `show_agent` via chained `waitForTransitionMs` long-poll calls (`repo` is required; pass the same `role` you spawned with to narrow to that agent). The response shape is `{ children: PolygraphChildStatusItem[] }` with one entry per matching agent in that repo. On your delegation's entry, inspect:
|
|
214
|
-
|
|
215
|
-
- `child.status` — one of `'created'`, `'in-progress'`, `'input-required'`, `'permission-required'`, `'completed'`, `'failed'`, `'cancelled'` (British double-L on `'cancelled'`).
|
|
216
|
-
- `child.inputRequiredQuestion` — populated only when `child.status === 'input-required'`.
|
|
217
|
-
- `child.lastOutputLines` — recent log tail.
|
|
218
|
-
- `child.repoFullName` — which repo is talking.
|
|
219
|
-
|
|
220
|
-
Drive the state machine:
|
|
221
|
-
|
|
222
|
-
- `child.status === 'in-progress'` or `'created'` — continue polling.
|
|
223
|
-
- `child.status === 'input-required'` — read `child.inputRequiredQuestion`, surface it to the user verbatim (e.g. "The child agent in `{child.repoFullName}` needs input: {child.inputRequiredQuestion}"), get the answer, then call `spawn_agent` again with the same `repo`, the same `role`, and `instruction: <answer>` — it is routed to that (repo, role)'s active task automatically. Continue polling.
|
|
224
|
-
- `child.status === 'completed'` — read `child.lastOutputLines`, proceed to `push_branch` + `create_pr`.
|
|
225
|
-
- `child.status === 'failed'` — read `child.lastOutputLines`, surface the failure.
|
|
226
|
-
- `child.status === 'cancelled'` — the child was stopped via `stop_agent`; see below.
|
|
227
|
-
- `child.status === 'permission-required'` — the child is waiting on a permission decision; see "Handling permission requests" below.
|
|
228
|
-
|
|
229
|
-
3. To abort mid-flight, call `stop_agent` with `{ sessionId, repo, role? }`. The response is:
|
|
230
|
-
|
|
231
|
-
```json
|
|
232
|
-
{
|
|
233
|
-
"taskId": "…",
|
|
234
|
-
"state": "cancelled",
|
|
235
|
-
"sessionPreserved": true,
|
|
236
|
-
"output": "…",
|
|
237
|
-
"message": "…"
|
|
238
|
-
}
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
Because `sessionPreserved: true`, the stopped agent's session can be restored later for context. After resuming, do not make changes or continue prior work until the user explicitly asks for changes.
|
|
182
|
+
## Delegating to other repos
|
|
242
183
|
|
|
243
|
-
|
|
184
|
+
Working across more than one repo, or delegating any task? Read [`reference/delegation.md`](reference/delegation.md) first — required. Delegation is the only way to act on other repos, and the reference holds the contract that keeps it cheap and trackable: skipping it leads to re-pasting briefs, polling in the main conversation, and touching other repos' clones directly — each of which burns tokens or breaks session tracking.
|
|
244
185
|
|
|
245
186
|
<!-- opencode-only gate. Claude and Codex parents handle permission gates via the native
|
|
246
187
|
MCP elicitation dialog and never see permission-required tasks in the polling loop —
|
|
@@ -363,15 +304,16 @@ If the session has a description timeline, also display:
|
|
|
363
304
|
|
|
364
305
|
## Best Practices
|
|
365
306
|
|
|
366
|
-
1. **
|
|
307
|
+
1. **Wait in background subagents** — `spawn_agent` is fine to call directly, but every waited `show_agent` poll MUST go through `@polygraph-delegate-subagent`; inline polling floods the context window with status noise.
|
|
367
308
|
|
|
368
|
-
1. **
|
|
309
|
+
1. **Read each result once** — when a poller exits, read that child with a single unwaited `show_agent(sessionId, id)`; `result.text` is the child's final message. Only reach for an explicit `tail` if that is not enough.
|
|
310
|
+
1. **Poll child status before proceeding** — Always verify child agents have reached a terminal `child.status` (`'completed'`, `'failed'`, or `'cancelled'`) before pushing branches or creating PRs
|
|
369
311
|
1. **Link PRs in descriptions** - Reference related PRs in each PR body
|
|
370
312
|
1. **Keep PRs as drafts** until all repos are ready
|
|
371
313
|
1. **Always pass `description`** when calling `create_pr`, `associate_pr`, or `update_session` — it is required and must follow the Session Description Policy
|
|
372
314
|
1. **Test integration** before marking PRs ready
|
|
373
315
|
1. **Coordinate merge order** if there are deployment dependencies
|
|
374
316
|
|
|
375
|
-
1. **NEVER
|
|
317
|
+
1. **NEVER run a waited `show_agent` loop in the main conversation**. Waiting MUST always go through `@polygraph-delegate-subagent`.
|
|
376
318
|
|
|
377
|
-
1. **Use `stop_agent` to clean up** — Stop child agents that are stuck or no longer needed (pass
|
|
319
|
+
1. **Use `stop_agent` to clean up** — Stop child agents that are stuck or no longer needed (pass the delegation id). The child's session is preserved (`sessionPreserved: true`) so the context can be restored later, but after resuming you must wait for explicit user instructions before making changes.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Delegation Reference
|
|
2
|
+
|
|
3
|
+
Delegation is the only way to act on a repository other than the one you are in. Polygraph keeps local clones of the other repos in the session, but they are not yours to touch: never `cd` into them, read their files, or run git in them. Everything happens through `spawn_agent` and `show_agent`.
|
|
4
|
+
|
|
5
|
+
The flow is **pointer-based**. `spawn_agent` hands you a delegation id. A cheap background subagent watches that id and tells you when it stops moving. You then read the answer yourself, once. Nothing re-pastes the brief, and no log lines pass through a middleman.
|
|
6
|
+
|
|
7
|
+
## The delegation id
|
|
8
|
+
|
|
9
|
+
`spawn_agent` returns a short id (e.g. `frontend-1`) that names one child run. It is the handle for everything afterwards — polling, reading the result, following up, stopping. The id pins the repo AND the role, so once you have it you never re-specify either.
|
|
10
|
+
|
|
11
|
+
Keep every id you are given. Losing one means falling back to `repo` + `role` lookups, which are ambiguous the moment a repo hosts more than one agent.
|
|
12
|
+
|
|
13
|
+
## Spawning
|
|
14
|
+
|
|
15
|
+
Call `spawn_agent` directly from the main conversation. This is a fast, non-blocking call that returns an id — it is not polling and does not belong in a subagent.
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
spawn_agent(
|
|
19
|
+
sessionId: "<sessionId>",
|
|
20
|
+
repo: "<org/repo-name>",
|
|
21
|
+
instruction: "<the task instruction>",
|
|
22
|
+
role: "<optional role>",
|
|
23
|
+
context: "<optional context>"
|
|
24
|
+
)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Write the instruction as if to a competent engineer who cannot see your conversation: state the goal, the constraints, and what "done" looks like. The child has its own repo and its own context; it inherits nothing from yours.
|
|
28
|
+
|
|
29
|
+
Delegate to several repos in parallel by calling `spawn_agent` once per repo before waiting on any of them.
|
|
30
|
+
|
|
31
|
+
**Own-repo rule.** With the default role, `repo` must be a repository other than the one you are working in — never delegate into your own repo with the default role; work on it directly (ordinary local subagents are fine for that). Delegating into your own repo IS allowed with an explicit non-default `role`, because each (repo, role) pair is a separate agent slot and the child then runs alongside your own default-role work without colliding with it.
|
|
32
|
+
|
|
33
|
+
## Waiting
|
|
34
|
+
|
|
35
|
+
For each id, launch one background poller subagent whose entire job is to block until that child stops moving. Give it the `sessionId` and the `id`, and nothing else.
|
|
36
|
+
|
|
37
|
+
- **Claude Code** — a background `Task` with `subagent_type: "polygraph:polygraph-delegate-subagent"`, `run_in_background: true`, and description `Delegate to <repo>`. Fall back to the bare agent name only if the namespaced form is not found.
|
|
38
|
+
- **OpenCode** — invoke `@polygraph-delegate-subagent`.
|
|
39
|
+
- **Codex** — launch `agent_type: "polygraph-delegate-subagent"` via Codex's own `spawn_agent`, and collect it with `wait_agent`.
|
|
40
|
+
|
|
41
|
+
The poller has exactly one tool and cannot read logs. It exits with a few lines naming the repo, the id, and the final status. That message is a doorbell, not a report — it tells you the child is worth reading, and nothing about what the child did.
|
|
42
|
+
|
|
43
|
+
**Routine polling never happens in the main conversation.** A waited `show_agent` loop run inline floods your context with status noise and is the single largest avoidable cost in a multi-repo session. That is what the poller exists to absorb.
|
|
44
|
+
|
|
45
|
+
## Reading the result
|
|
46
|
+
|
|
47
|
+
When a poller exits, read the child's answer yourself with a single **unwaited** `show_agent` — no `waitForTransitionMs`, no `tail`:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
show_agent(sessionId: "<sessionId>", id: "<id>")
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`result.text` is the child's final message: what it did, what it found, what it wants you to know. This is the payload. Read it once, in the main conversation, and act on it.
|
|
54
|
+
|
|
55
|
+
One-off unwaited reads like this are cheap and expected inline. It is the *waiting* that belongs in a subagent, not the reading.
|
|
56
|
+
|
|
57
|
+
## When the result is not enough
|
|
58
|
+
|
|
59
|
+
Only if `result.text` is missing, truncated, or the child failed in a way you cannot explain from it:
|
|
60
|
+
|
|
61
|
+
- Pass an explicit `tail` to `show_agent` to pull recent log lines.
|
|
62
|
+
- Page further back with the `page` param: `tail: 5, page: 2` returns the 5 lines before the newest 5, `page: 3` the window before that.
|
|
63
|
+
- If the user wants to watch the run live, point them at `polygraph agent attach <repo>` (plus `--role <role>` for a non-default agent) — an interactive terminal view for humans, not a command for you to run.
|
|
64
|
+
|
|
65
|
+
These are deliberate, targeted follow-ups. None of them belongs in a polling loop, and none of them is a reason to go looking at transcript files, `~/.polygraph/sessions`, or anything a harness saved to disk because a tool result was too large. `show_agent` is the supported interface.
|
|
66
|
+
|
|
67
|
+
## Follow-ups
|
|
68
|
+
|
|
69
|
+
To send a child more work, call `spawn_agent` again with the SAME `repo` and the SAME `role`. If that (repo, role) still has a live task — working, or paused waiting on you — the orchestrator delivers your instruction to it as a follow-up instead of starting a second run. A (repo, role) pair therefore has at most one active child at a time.
|
|
70
|
+
|
|
71
|
+
A follow-up returns a **new** delegation id, linked to the previous one by a `continues` reference. The new id is the live handle: poll it, read it, follow up on it. The old id still addresses the earlier turn if you need to look back at it.
|
|
72
|
+
|
|
73
|
+
After a follow-up, launch a fresh poller subagent for the new id. The old poller has already exited; it does not resume.
|
|
74
|
+
|
|
75
|
+
## Input-required
|
|
76
|
+
|
|
77
|
+
When a child needs an answer from you, it stops and the poller exits with status `input-required` and "needs attention."
|
|
78
|
+
|
|
79
|
+
Read the child with an unwaited `show_agent` as usual. `inputRequiredQuestion` carries the child's verbatim question. Surface it to the user as the child asked it — do not paraphrase or answer on the user's behalf — then send the answer back as an ordinary follow-up `spawn_agent` for the same (repo, role). Poll the new id it returns.
|
|
80
|
+
|
|
81
|
+
`permission-required` is a different state and is not yours to resolve here; see "Handling permission requests" in the skill.
|
|
82
|
+
|
|
83
|
+
## Roles
|
|
84
|
+
|
|
85
|
+
A repository in a session can host several child agents at once, distinguished by **role**:
|
|
86
|
+
|
|
87
|
+
- **Omit by default.** Set a `role` only when the user very explicitly asked for a named one, or when a skill the user invoked prescribes one (e.g. `adversarial-review` uses `reviewer`). Never invent one.
|
|
88
|
+
- **Purpose.** Roles let independent streams of work run concurrently in one repo — a default agent implementing a feature while a `reviewer` or `ci-investigator` runs alongside. Each (repo, role) pair has at most one active child.
|
|
89
|
+
- **Default role.** An omitted `role` means the default role: `spawn_agent` without `role` starts or follows up with that repo's default-role agent.
|
|
90
|
+
- **Ids pin the role.** A delegation id already identifies one (repo, role) pair, so `show_agent` and `stop_agent` by id need no `role` argument. Pass `role` only when addressing an agent by `repo` instead of by id.
|
|
91
|
+
- **Logs.** Only default-role agents upload logs to the cloud and appear in the multiplexed stream (`polygraph session logs`). A non-default agent's transcript stays on this machine — the user can watch it with `polygraph agent attach <repo> --role <role>`.
|
|
92
|
+
|
|
93
|
+
## Stopping
|
|
94
|
+
|
|
95
|
+
Cancel a running child by id:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
stop_agent(sessionId: "<sessionId>", id: "<id>")
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The response reports `sessionPreserved: true`: the stopped agent's session is kept so its context can be restored later. Restoring is read-only. After a resume, do not continue the prior work or make further changes until the user explicitly asks for them.
|
|
102
|
+
|
|
103
|
+
## Before publishing
|
|
104
|
+
|
|
105
|
+
Every delegation must reach a terminal status — `completed`, `failed`, or `cancelled` — before you push branches or open PRs. A poller exiting on `input-required` is not terminal; it means the child is still waiting on you.
|
|
@@ -29,7 +29,7 @@ For a fresh Codex Desktop conversation started with `/polygraph:session-start`,
|
|
|
29
29
|
|
|
30
30
|
Pick one path before using tools.
|
|
31
31
|
|
|
32
|
-
1. **Existing session with repos** - If a Polygraph session ID is already in scope and the user did not ask to add repositories,
|
|
32
|
+
1. **Existing session with repos** - If a Polygraph session ID is already in scope and the user did not ask to add repositories, pick by intent: to continue the session's work from this conversation, join it via `resume_session`; to only inspect it, call `show_session` and print the session details. Do not create a new session.
|
|
33
33
|
2. **Existing session, adding exact repository refs** - If a session ID is in scope and the user provided exact refs by ID, short name, full name, GitHub `owner/repo` slug, URL-like slug, or MCP resource syntax, call `add_repo(sessionId, repoIds: [...])` directly. Do not run discovery.
|
|
34
34
|
3. **Existing session, discovery needed** - If a session ID is in scope but repos need to be discovered or selected, launch `polygraph-init-subagent` with the existing `sessionId` and `userContext`. The subagent must use `add_repo`, not `start_session`.
|
|
35
35
|
4. **No session in scope** - Launch `polygraph-init-subagent` with `userContext` and no `sessionId`. The subagent will discover related repositories when needed and call `start_session`.
|