Delegation
Agents that hand off work — and get it back
A main agent in pm7Code can hand a well-defined subtask to a sub-agent. pm7Code starts the sub-agent itself — no Start click, no human in the loop — in its own git worktree, and delivers the outcome back to the main agent as a new message. That works in the same project, in another project on the same machine, and in a project on another pm7Code server in your network. The whole loop runs inside the engine, so it keeps going with no pm7Code window open.
Concept
What delegation is
Big jobs contain parts that do not need the main agent's full attention: write the tests for a module, update the docs in a sibling project, port a fix to another service. With delegation the main agent (the parent) hands such a part to a sub-agent (the child), keeps its own context clean, and continues with the result when it comes back.
You do not have to approve anything. The agent decides to delegate, pm7Code checks the request against the rules of the machine, starts the sub-agent, watches it finish, and hands the outcome back. You see every step on a card in the chat and can stop any sub-agent there.
The agent delegates
It emits one DelegateRequest block per subtask and ends its turn. No polling, no waiting.
A sub-agent works
In its own worktree and branch, with any agent you allow — on this machine or on another server.
The outcome returns
As a new message for the main agent: branch, result commit, diff stat, the sub-agent's report — or its question.
DelegateRequest block in its system prompt, and a sub-agent gets a notice that it is one. You can narrow or switch it off per engine; see Settings.Concept
Delegation vs. TopicStartRequest
pm7Code has two ways for an agent to get other work started. They look alike but serve different purposes.
| DelegateRequest | TopicStartRequest | |
|---|---|---|
| Who starts it | The agent. pm7Code starts the sub-agent itself — no card to click. | You. Nothing runs until you press Start on the card. |
| Where it runs | Inside the engine. It keeps running with no pm7Code window open. | Started from the client, as a new topic. |
| What comes back | Always: the outcome arrives as a new message for the main agent — also after an engine restart, also when the main agent was asleep. | Only with waitFor: true, and only while a pm7Code client is open. |
| Git | Its own worktree and branch, starting from the main agent's commit (or from the target project's default branch). | A normal topic with its own session. |
| Where you see it | A Sub-agent card in the main agent's chat, with live status and a Stop button. | A new topic in the sidebar. |
| Good for | Well-defined subtasks the main agent needs back to finish its own job. | Separate work you want to follow and steer yourself. |
How it works
How a delegation runs
Every delegation follows the same loop. All of it happens in the pm7Code engine; the client only shows it.
The main agent's turn ends
pm7Code reads the DelegateRequest blocks of that turn right away and reserves them, so a sleep or a closed window afterwards cannot lose them. Each block is recognised by its message and position: the same block never starts two sub-agents.
pm7Code checks the request
Delegation is on, the requester is not itself a sub-agent, the agent is allowed, the target project exists and is allowed, the hourly limit is not reached, and the project is a git repository with at least one commit. Within the same project the main agent's worktree must also be clean (the .pm7-code folder does not count). A refusal is not silent: it comes back to the main agent as a failed result with the reason.
The sub-agent starts
A new session in its own git worktree. In the same project its branch starts at the main agent's current commit; in another project at the tip of that project's default branch. With the same agent it inherits the main agent's start options (model, permission mode, effort and the like; to another server only a fixed set travels along). By default at most 4 sub-agents run at once per machine and 3 per main agent; the rest waits in the queue. The first turn wraps the prompt in a <DELEGATED_TASK> envelope.
The sub-agent finishes a turn
pm7Code waits for running git jobs, then decides, in this order: stopped → cancelled; turn did not complete → failed; open question → blocked; uncommitted work → one reminder to commit, then blocked; otherwise done, with the result commit, the number of commits, the diff stat and the changed files.
The outcome is delivered
As one visible message to the main agent, when it is live and idle. Otherwise it waits until the main agent's turn ends or its session starts again — and after an engine restart pm7Code wakes it. See Results always arrive.
Afterwards
The sub-agent sleeps. Its worktree stays as long as it holds commits or changes. A follow-up resumes the same sub-agent on its own branch, through the same queue, running limits and policy as a new task (the hourly limit only counts new tasks). It is possible once the task is blocked, done or failed and its sub-agent exists; otherwise the main agent gets a short note instead.
Agent protocol
The DelegateRequest block
The agent asks for a sub-agent with a fenced block. One block per subtask; several blocks in one message run in parallel. After the blocks it ends its turn — the result arrives by itself.
A new task in the same project
```DelegateRequest
{
"name": "Add retry to the uploader",
"prompt": "In src/upload.ts, retry failed uploads up to 3 times with exponential backoff (1s, 2s, 4s). Add tests in src/upload.test.ts. Verify with npm test. Commit your work.",
"agent": "codex"
}
```A task in another project, landed after green tests
```DelegateRequest
{
"name": "Document the new retry option",
"prompt": "Add a section 'Retries' to docs/uploads.md describing the retry option (3 attempts, backoff 1s/2s/4s). Commit your work.",
"project": "pm7-Docs",
"land": true
}
```When the same project name exists on several servers, name the server too: "project": { "name": "api", "server": "3f2a9c41" }
An answer or a follow-up
```DelegateRequest
{ "taskId": "dt_3f9a1c2b7e4d", "prompt": "Use 5 attempts instead of 3, keep the rest." }
```Stop a sub-agent
```DelegateRequest
{ "taskId": "dt_3f9a1c2b7e4d", "cancel": true }
```| Field | When | Meaning |
|---|---|---|
| prompt | required (new task, follow-up) | The instructions for the sub-agent, up to 20,000 characters (longer is cut off). Write them self-contained: the sub-agent has none of the main agent's conversation. State the goal, the files involved, the constraints, and how to verify. |
| name | optional | A short name for the task, up to 80 characters (longer is cut off). Shown on the card and in the result. Defaults to the first line of the prompt. |
| agent | optional | Which agent does the work: claude-sdk, codex, pi-sdk, pm7-code, cursor-acp or grok-acp. Defaults to the main agent's own agent. The machine's delegationAgents setting decides which are allowed. |
| project | optional | Work in another project: its name or id as a string, or { "name": "…", "server": "<server id>" } when the same name exists on several servers (a server id prefix of at least 8 characters is enough; the object form needs a name). Omit it to work in the main agent's own project. |
| land | optional, only with project | Literally true: after the sub-agent finishes with commits, pm7Code tests them and fast-forwards the target project's default branch to exactly that commit. Needs a per-project opt-in; see Landing. |
| taskId | follow-up, answer, stop | The id of an existing task (dt_…) of this topic. With prompt: an answer to the sub-agent's question, or a new instruction once it is blocked, done or failed (not while it is queued or running, and not after a stop). With cancel: stop it. |
| cancel | stop | Literally true, together with taskId: stop that sub-agent. |
Commit first
Within the same project, pm7Code refuses the request while the main agent's worktree has uncommitted changes: the sub-agent starts from its commit and would not see them. In another project this does not matter.
End the turn, do not poll
The outcome arrives as a new message. Only delegate work that is independent of what the main agent still changes itself.
Merge it yourself (same project)
The sub-agent commits on its own branch. The main agent merges the result commit into its own branch (git merge <commit>) and lands through the normal path. Nothing lands in the project base automatically.
Questions come back
A sub-agent that needs a decision asks it with a CViewQuestion and ends its turn; nobody watches it live. The main agent receives the question at once and answers with { "taskId", "prompt" }.
Results
Statuses and results
| Status | Meaning |
|---|---|
| queued | Accepted, waiting for a free slot (running limits) or, on another server, for that server to accept the task. |
| running | The sub-agent is working. |
| blocked | The sub-agent needs the main agent: it asked a question, left uncommitted work after a reminder, or its work could not land. It waits for an answer or instruction. |
| done | Finished. The result names the branch, the result commit, the number of commits, the diff stat and the files — or says that nothing changed. |
| failed | Refused before it started (with the reason), the sub-agent's turn did not complete, or the engine restarted mid-turn. A follow-up can let the same sub-agent continue on its branch. |
| cancelled | Stopped — by the main agent or by you on the card. (A policy change does not stop a running sub-agent; a queued start it forbids becomes failed.) |
The main agent receives each outcome as one visible message. A finished task in the same project:
<DELEGATION_RESULT taskId="dt_3f9a1c2b7e4d" name="Add retry to the uploader" status="done" agent="codex">
The sub-agent finished with 2 commit(s) on branch pm7/s-8c1d2e3f.
Result commit: 9b1e04c7a2… (starts from your commit 4a7c21e0d3; 2 files changed, 48 insertions(+), 6 deletions(-)).
Files: src/upload.ts, src/upload.test.ts
Merge it into your branch yourself: git merge 9b1e04c7a2…
Sub-agent's final message:
Retries added with backoff 1s/2s/4s; 6 new tests, npm test passes.
</DELEGATION_RESULT>A sub-agent that needs a decision:
<DELEGATION_RESULT taskId="dt_3f9a1c2b7e4d" name="Add retry to the uploader" status="blocked" agent="codex">
The sub-agent stopped with a question for you:
Should a 4xx response also be retried, or only network errors and 5xx?
Answer or instruct it with a DelegateRequest { "taskId": "dt_3f9a1c2b7e4d", "prompt": "..." }, or stop it with { "taskId": "dt_3f9a1c2b7e4d", "cancel": true }.
</DELEGATION_RESULT>For another project the result names the project, the server and the folder, and says the work stays on that branch there; with land it reports what happened:
Landed: main in project "pm7-Docs" moved from 1c0ffee123 to 7d3b9a0e44 (fast-forward, after `npm test` passed). Not pushed.In the app
The Sub-agent card
Each DelegateRequestblock appears in the main agent's chat as a Sub-agent card. It shows the live status, the branch, the result commit and diff stat, an error or open question, and — for another project — the project and server. While a task is open, the card has a Stop button. During landing it shows testing or landing, then landed: <sha>. Follow-up and stop blocks show only what was asked.
The card updates live while you watch. When you open an older conversation, it fetches the current state of its task.
Parallel work
Fan-out: several sub-agents at once
Several new DelegateRequest blocks in one turn of the main agent form a group. They start in parallel within the running limits (on this machine 3 per main agent by default); the rest waits in the queue.
One delivery for the group
Finished outcomes (done, failed, cancelled) are held while another member is still queued or running. Then they arrive together in one message; when the whole group is finished it starts with “All N sub-agent tasks you started together have finished” and a count per status.
Questions do not wait
A blocked member (a question, uncommitted work) reaches the main agent at once, also mid-fan-out. The others keep working and do not wait for that answer.
What is not a group
A single block, or a follow-up to an existing task, does not start a new group.
Scope
Another project on the same machine
Add "project" and the sub-agent works in that project instead. pm7Code looks it up in your pm7Code workspace — the same projects you see in the sidebar.
Finding the project
By id or exact name; only when neither matches, by case-insensitive name. server narrows it to one server (the full id, or a prefix of at least 8 characters). Several matches: pm7Code refuses and lists the candidates with their server and folder. No match: it refuses and lists the projects on this machine. It never guesses.
Where the sub-agent starts
The project folder must exist on that machine and be the top of a git repository. The sub-agent branches from the tip of the project's default branch (origin/HEAD, main, master, then HEAD) — not from whatever happens to be checked out. Uncommitted work of the main agent or in the target does not matter.
Where the result goes
The work stays on the sub-agent's branch in that project; the main agent does not merge it into its own branch. It lands there only with "land": true. A follow-up goes to the same sub-agent in the same project.
Who may do this
Only a topic with a signed-in pm7Code user (the lookup needs your workspace). The delegationProjects setting decides which project may delegate to which; it is checked again for every follow-up and queued start (a running sub-agent is not stopped by it).
delegationProjects setting, every project of the same user on the machine is allowed — a deliberate choice: a sub-agent only writes on its own branch, and landing needs its own opt-in per target project.Scope
Another server in your network
The target project may also live on another pm7Code server — a build box, a Linux server, a second Mac. The sub-agent then runs on that machine, under that machine's rules, and the outcome travels back to the main agent. For the agent nothing changes: it names the project, pm7Code finds the server.
One hub
The main machine — the one that holds your pm7Code workspace — is the hub. As hub it only routes and remembers which engine is which server; tasks are stored by the engines that run them.
Members link in
Every other enrolled machine keeps one WebSocket link open to the hub, with its own narrow credential.
Tasks are routed
The hub routes the start by server id to the machine of the target project. Results, follow-ups and stops then go by machine id between the two engines.
Two sides of one task
On the machine of the main agent (the origin) the task is a stand-in that keeps an outbox and the last state it heard. On the target machine (the executor) it is an ordinary task with its own worktree, tests and landing. The executor checks everything itself before it accepts:
- delegation is on there, and the agent is allowed there;
- the project really is in your workspace, on exactly that server, with the same folder;
- its own
delegationProjectsallows the pair; - the git state is usable, and with
landthe project there allows landing; - it holds fewer than 20 open (queued, running or blocked) tasks for that origin machine.
Of the main agent's start settings only model, permissionMode, effort, thinkingLevel and disallowedToolstravel along (with the same agent). Never keys, never engine settings. Such a task counts only toward the executor's own delegationMaxRunning, not toward the running limits on the main agent's machine.
| Direction | Message | Purpose |
|---|---|---|
| origin → executor | start | Take on the task. Deduplicated per attempt, so a retry never starts a second sub-agent. |
| origin → executor | cmd | A follow-up or a stop. Deduplicated per command. |
| origin → executor | probe | Do you still know this task? Sent when a running task has been silent for 10 minutes. |
| executor → origin | result | Status and outcome, numbered, resent until the origin confirms it stored it. |
| executor → origin | note | A short message for the main agent. |
Every answer is ok, refused (final — the main agent gets the reason) or unreachable (try again later). An unexpected error on the receiving side counts as unreachable: an outcome only counts as delivered once the other side really stored it.
When things go wrong
| Situation | What pm7Code does |
|---|---|
| The other server is unreachable when the task starts or stops | The origin retries every 30 seconds and immediately after the link reconnects. A start that is not accepted within 15 minutes fails honestly (“the task did not start”). A follow-up or stop that cannot be delivered is given up after 24 hours: the follow-up with a note, the stop by cancelling the task here — the sub-agent there may have kept working, and what it reports later no longer counts. |
| The answer to a start gets lost | The retry gets the same task back instead of a second one. Results also carry the task id, so the origin learns it either way. |
| A stop arrives before the start | The stop wins. The executor keeps a marker for that attempt and refuses the late start — also when the stop arrives while the start is still being checked. |
| The executor restarts | A running sub-agent turn, or a task still in its queue, does not survive; the task becomes failed with an honest message. That outcome is stored there and still sent to the origin until confirmed. |
| The origin restarts | The task is stored on disk. An outcome that arrives later wakes the main agent (see Results always arrive). |
| No news for a long time | After 10 silent minutes the origin sends a probe. If the executor no longer knows the task, it fails. A running task that gives no sign for 24 hours fails on the origin; an outcome that still arrives after that is delivered as a new result. |
Security model
A separate, narrow credential
Delegation members use their own credential, stored on the hub in ~/.pm7-code/delegation-peers.json (hash only, mode 0600) — separate from engine peers. A delegation member gets no gateway keys and no configuration secrets, and an engine peer is not automatically a delegation member.
One user per machine
Every enrolled machine belongs to exactly one pm7Code user. The hub only gives it that user's projects and tasks, and refuses its messages for anyone else. Every task on an executor belongs to one user as well.
Revoke counts at once
Enrollment is checked on every message, not only at connect. A revoked machine is refused from its next message on. Enrolling the same machine again invalidates its old link.
Only your own servers
A member can only claim server ids that appear in its own user's workspace. The first claim wins; a second engine for the same server id gets a conflict, not a guess. A member socket receives no broadcasts and cannot run normal client operations.
Setup
Enrolling a server
Enrolling is the opt-in: a machine takes part in delegation only after you enroll it on the hub. You do this once per machine, from a shell on the hub.
# On the main machine (the hub: the one that holds your pm7Code workspace)
pm7code delegation enroll build-box \
--address wss://hub.example.net:8787 \
--out ./build-box.json \
--label "Build box"
# Enrolled build-box for user <your user id>.
# Copy ./build-box.json to that machine as ~/.pm7-code/delegation-peer.json
# (keep it private), then restart its engine.
# Which machines are enrolled, and when they were last seen
pm7code delegation list
# Withdraw a machine: its link is refused from its next message on
pm7code delegation revoke build-boxPick a name for the machine
The first argument is the machine id the link will use: letters, digits, dot, underscore and dash, up to 64 characters — for example build-box or server2.
Give the hub's address
--addressis where the other machine reaches this machine's pm7Code engine: wss://… or ws://… with host and port. Use wss:// unless the network between the two is trusted — with ws:// the token travels unencrypted, and the command warns about that.
Choose the output file
--out receives the link file (mode 0600). The token is written only there — never to the screen. The command refuses to overwrite an existing file. --user may be left out when the hub has exactly one pm7Code workspace; otherwise it lists the users to choose from. --label is a free-text description for list.
Install it on the other machine
Copy the file to that machine as ~/.pm7-code/delegation-peer.json, keep it private, and restart its engine. At start the engine picks its role: with a link file it is a member; the main machine (or a standalone engine) without one is the hub.
Use it
Open a project on that server in pm7Code once, so its engine learns which server id it is and claims it at the hub. From then on any agent can delegate to projects there.pm7code delegation list shows each enrolled machine and when it last connected.
pm7code delegation revoke <id> on the hub and enroll the machine again — other machines keep working.Finishing
Landing: finished work straight into the project
With "land": truethe work of a sub-agent in another project does not stay on a side branch: after the sub-agent finishes with commits, pm7Code tests exactly that commit and moves the target project's default branch to it (when the branch already contains it, nothing moves and it counts as landed). Narrow on purpose — it is a fast-forward after green tests, nothing more.
Opt-in per target project
Landing is allowed per target project, locally in its .pm7-code/project.json (not in git):
// <target project>/.pm7-code/project.json — local, not in git
{
"delegation": {
"land": {
"enabled": true,
"testCommand": "npm test",
"timeoutMs": 900000
}
}
}Without enabled: true or without a testCommand, pm7Code refuses a request with land right away and says how to turn it on — no sub-agent is started. timeoutMs is optional: 10 seconds to 60 minutes, default 15 minutes. The opt-in is read again just before landing; if it was switched off meanwhile, the task is donewith “Not landed: …” and the work stays on the branch.
Test first
The testCommand runs with sh -cin the sub-agent's worktree, on the result commit, with CI=1 and PM7_DELEGATION_LAND=1, in its own process group: a timeout, a Stop and the end of the command also stop whatever it started in the background. The worktree must equal the commit before the test, and the test may not change tracked files (generate, format) — otherwise it did not test that commit, and the sub-agent gets a turn to commit or revert.
Then only a fast-forward
Under the target project's lock: the base checkout must have the default branch checked out, no build or git operation may be running, and the branch must be an ancestor of exactly the tested commit. Then git merge --ff-only --no-autostash in the base checkout. Uncommitted work there that the merge touches makes git refuse.
The sub-agent repairs first
Red tests, or a default branch that moved on (typical with fan-out into one project), give the sub-agent an extra turn with the facts: the last test output, or “merge main”. At most 2 such turns per instruction; then the task is blocked with the output. A follow-up from the main agent starts the count again.
What the sub-agent cannot fix
Base checkout on another branch, uncommitted changes in the base that the fast-forward would touch, a build or git operation running there, a git error: blocked at once, with the facts, without an extra turn. Unrelated uncommitted files in the base stay as they are.
Never pushed
Landing moves the local default branch only. pm7Code never pushes, builds or deploys. Only your testCommandruns — whatever you put there.
Only for another project
In its own project a fast-forward would also carry the main agent's own unlanded commits. There the main agent merges the result itself.
Survives a restart
A restart mid-landing is finished by the new engine: already landed counts as done; otherwise test and fast-forward again, at most 3 attempts, then blocked. A Stop stays a Stop.
Reliability
Results always arrive
An outcome must reach the main agent, also when nobody is watching. pm7Code keeps every task in a register on disk (~/.pm7-code/delegation-tasks.json, per engine) and tracks the delivery of each outcome separately. Finished tasks stay there for 30 days, or 90 days while their outcome is not yet delivered.
Delivered means: seen
An outcome goes from pending to sent when it is handed to the main agent, and only becomes delivered when the main agent's next turn ends. Closing the main agent mid-turn, or an engine restart, puts it back to pending. A newer outcome is never marked as delivered by an older one.
No sleep while work is out
A main agent with a running or queued sub-agent, or with an outcome that is not yet confirmed, does not go to sleep. A blocked sub-agent does not count: it waits for the main agent.
Woken after a restart
After an engine restart pm7Code starts a waiting main agent by itself — with the same owner, workspace user, settings and worktree choice it had — and delivers the outcome. When you then open that topic, the app takes over the woken session instead of starting a second one. Only if you open it deliberately fresh, or with another agent, folder, model, permission mode, effort or thinking level, pm7Code closes the woken session first and the new one receives the outcome.
No window needed
The loop lives in the engine. Close pm7Code, and sub-agents keep working, outcomes keep arriving, and the main agent keeps continuing with them.
Configuration
Settings
Delegation is configured per engine in ~/.pm7-code/settings.json. Every machine decides for itself: an executor applies its own settings to tasks from other servers.
| Key | Default | Meaning |
|---|---|---|
| delegationEnabled | true | Turn delegation on or off for this engine. Off also means: this machine accepts no tasks from other servers. |
| delegationMaxRunning | 4 | Sub-agents running at the same time on this engine. The rest waits in the queue. |
| delegationMaxRunningPerParent | 3 | Sub-agents running at the same time for one main agent. |
| delegationMaxPerParentPerHour | 20 | New delegations one topic may start per hour. |
| delegationAgents | all known agents | List of agent ids that may be used as sub-agent on this engine. |
| delegationProjects | absent = every project of the same user | Which project may delegate to which other project. An object from source to targets, by name (case-insensitive) or id, with * as wildcard. Absent or null allows everything; {} or any other non-object value turns delegation to other projects off. |
// ~/.pm7-code/settings.json on the engine
{
"delegationMaxRunning": 6,
"delegationAgents": ["claude-sdk", "codex"],
"delegationProjects": {
"pm7-Code": ["pm7-Docs", "site"],
"*": ["Sandbox"]
}
}In this example the project pm7-Code may delegate to pm7-Docs and site, and every project may delegate to Sandbox. Anything else to another project is refused. Closing a pair does not stop a sub-agent that is already running; a queued start in that pair then fails, and follow-ups are refused.
.pm7-code/project.json; see Landing. Machines for other servers are enrolled on the hub; see Enrolling a server.Safety
Guardrails
Own worktree, own branch
A sub-agent never works in your checkout. Without a worktree there is no sub-agent.
No push, no build, no deploy
pm7Code itself never pushes, builds or deploys as part of delegation, and sub-agents are instructed not to push or land. Landing is a local fast-forward after green tests. With another server, the prompt and the outcome travel between your own machines.
No chains
A sub-agent cannot delegate further: pm7Code ignores its DelegateRequest blocks, and it is told not to emit a TopicStartRequest either.
Limits
By default 4 running per machine, 3 per main agent, 20 new per topic per hour, 20 open per origin machine on an executor. All but the last are settings; each machine applies its own.
Same owner
A sub-agent belongs to the same user as its main agent, and inherits its isolation. Tasks from one user are invisible to another.
Never twice
New tasks, follow-ups and stops are deduplicated durably: a retry, a reconnect or a restart never starts a second sub-agent for the same block.
Honest failures
A worktree that git cannot inspect is reported as a failure, never as “clean”. A refusal always carries the reason.
You can always stop it
The Stop button on the card or a stop from the main agent — a stop during start-up is carried out as soon as the sub-agent exists. A fast-forward that has already happened is not undone.
Honest limits
What it does not do (yet)
- No deploy, no push, no build. Delegation ends at a commit on a branch, or at a local fast-forward with
land. That sub-agents do not push is an instruction to them, not a technical lock. - Sub-agents are not topics in the sidebar.You follow them on the Sub-agent card in the main agent's chat.
- Enrolling is command-line only. There is no button in the app yet; you run
pm7code delegation enrollon the hub and copy one file per machine. - The hub must be the machine with your workspace. There is no discovery in the network: members reach the hub at the address given at enrollment.
- “This Mac” entries are not routed. They mean something different on every device, so pm7Code does not send tasks there from another machine.
- A running sub-agent turn does not survive an engine restart. The task becomes
failedwith an honest message; a follow-up lets the sub-agent continue on its branch. A task still in the queue also fails and has to be delegated again. - No landing in the main agent's own project. There the main agent merges the result itself.
- Older app versions do not tell the engine which server a project is on. The engine then works it out from the folder, and such a session cannot claim its server for delegation from other machines.
- A reinstalled member does not know its old tasks. Enrolled again under the same machine id, the next probe fails them on the origin. Under a new id, running ones fail after 24 hours without word, and ones that were still queued there stay queued on the card until you stop them.
- Untracked files created by the land test do not count. A test that relies on such a file can pass while the commit does not contain it.
- Waking needs a topic opened in the app on a version with delegation; CLI and API parents are not woken.
- A stop that cannot reach another server for 24 hours cancels the task here; the sub-agent there may have kept working, and what it reports afterwards is ignored.
- Long texts are cut off. Prompts over 20,000 and names over 80 characters are shortened, not refused. Reports keep up to 12,000 characters of the final message, 40 file names and the last 3,000 characters of a failing land test.
- A machine's “last seen” in
pm7code delegation listis its last connect, not its last message. - The register is kept for 30 days (90 while an outcome is undelivered). Older finished tasks cannot be continued.
Help
Troubleshooting
Refusals come back to the main agent as a failed result with one of these messages. What to do:
| Message | What to do |
|---|---|
| Your worktree has uncommitted changes (…). Commit them first … | The main agent must commit first: the sub-agent starts from its commit and would not see uncommitted work. Only applies within the same project. |
| Delegation is turned off on this machine (delegationEnabled). | Remove "delegationEnabled": false from ~/.pm7-code/settings.json on that engine. |
| Agent "…" is not available for delegation here. Allowed: … | Use one of the listed agents, or add it to delegationAgents. |
| Too many delegations from this topic in the last hour (limit N). | Wait, or raise delegationMaxPerParentPerHour. Only new tasks count (not follow-ups), and refused ones do not. |
| There is no project "…" / Project name "…" is ambiguous: … | Use the exact name or id from your workspace (a no-match refusal lists the projects on this machine). When the name exists on several servers, add "server": "<server id>" — the ambiguity refusal lists the candidates with server and folder. |
| Delegating from "A" to "B" is not allowed on this machine (settings.json delegationProjects). | Add the pair to delegationProjects, or remove the setting to allow every project of the same user. |
| This topic has no signed-in pm7Code user … | Delegation to another project needs a signed-in workspace (it looks the project up there). Delegate within the same project, or sign in. |
| Project "…" does not let sub-agents land their work … | Add the land opt-in to <project>/.pm7-code/project.json, or delegate without "land". |
| Project … is on another server, and this machine is not linked to the other servers for delegation … | Enroll the machines (see Enrolling a server) and restart their engines. |
| Server … was claimed by two machines (engines … and …); pm7Code does not guess. | Remove the wrong entry from ~/.pm7-code/delegation-servers.json on the hub (the main machine). |
| pm7Code does not know which machine server … is yet. Open a topic on that server once … | Open any topic in a project on that server once, so its engine registers which server it is at the hub. |
| Project … is on a device's own "This Mac" entry; pm7Code cannot route a task there from another machine. | Add that machine as a real server in pm7Code (with its own server id) and use the project there. |
| "land" only applies to a task in another project. … | Within the main agent's own project, drop "land" and merge the result commit yourself. |
| DelegateRequest: task "…" is running; a follow-up is only possible when it is blocked, done or failed. | Wait for the outcome, then send the follow-up. A stopped task cannot be continued; start a new one. |
| pm7Code could not reach server … for 15 minutes (…); the task did not start. | Check that the other engine runs and that its link file points at the hub's address. pm7code delegation list on the hub shows when it last connected. |
| That machine already runs 20 tasks for this one; wait until some finish. | The executor caps open tasks (queued, running and blocked) per origin machine at 20. Wait until some finish, answer blocked ones, or stop ones you no longer need. |
More about the agent protocol, TopicStartRequest cards, worktrees and the Git Service is in the main documentation. Driving the engine from your own code is covered in the API reference.