Skip to content

Multi-agent system

Main and worker prompts ask for short attributed notes in work://shared/ when there is something to hand off or a reusable lesson, and the current request permits shared-file writes. Routine tasks need no ceremonial note. Standalone Plan permits session-owned plan edits but excludes shared and memory writes. Explorer, verifier, and reviewer report observations and hypotheses through existing results or an available SendMessage; they receive no extra write authority. Reviewer lessons stay within its existing JSON response schema. Only the main prompt receives the recent journal map; all roles may use permitted journal reads on demand.

The model-facing Agent tool starts a retained child asynchronously. It accepts a free-form task_name, a complete message, and optional role, context, model, effort, and working_directory controls, then returns the committed canonical path after preparation and provider dispatch succeed.

Work directly by default. Delegation earns its overhead for useful parallel work or fresh-context investigation returning compact results. The task message owns the assignment, file ownership, and expected result even when dialogue is copied. The contract keeps these decisions and authority limits inline; name normalization and lifecycle reference details live here behind its mevedel://agents.md pointer.

Delegation and result guidance asks for labeled measurement lists rather than compressed numeric strings. Each item names its scenario/configuration, metric, value, unit, and statistic or sample count; distinct metrics stay separate.

The harness lowercases the name, replaces runs outside [a-z0-9_-] with hyphens, trims boundary hyphens, and caps the base at 40 characters, preferring the last hyphen boundary. An empty result becomes agent; root becomes agent-root. Reservation adds -2, -3, and so on until the path is unique among retained and preparing siblings. For example, Review code-block copy becomes /root/review-code-block-copy for a root child, or /root/review-code-block-copy-2 if the first path is occupied. Callers use the returned path for follow-ups; a repeated name creates a new conversation, not a continuation. Canonical path inputs remain strict lowercase ASCII paths.

An omitted role selects default and inherits the delegator's effective instructions, tools, model policy, and delegation capability. A named role supplies its own configuration rather than intersecting its tools with the delegator's. Children are created below the caller, so recursive delegation forms paths such as /root/implementation/tests. Without working_directory, conversations inherit their parent's directory; when no ancestor selected an override, they use the root session's working directory, including fresh agents in a Worktree Fork. The workspace's original checkout root does not override that session directory. A shell-local cd in one Bash call changes only that process; it does not retarget later tool calls or children. A task message naming another checkout also does not change execution state.

working_directory selects an existing directory, absolute or relative to the parent's effective directory. It is canonicalized, including symlinks, on the session's execution target. The directory must be within the session workspace, or within a registered Git worktree of the workspace's repository. External worktrees are checked against the canonical common Git directory and the repository's current worktree list; unrelated repositories, symlink escapes to unrelated directories, and paths naming another execution target are rejected. Subdirectories of a registered checkout are accepted. Validation happens before reservation for an explicit argument and again before each provider turn. Missing or no-longer-related directories fail rather than silently falling back.

The selection is durable across retained follow-ups, save/restore, and Save As; children inherit it unless they select another directory. Conversation Fork and Worktree Fork still start with no retained agents under ADR 0062. Fresh agents there inherit the forked session's directory. The directory applies consistently to Bash and Eval, ordinary relative Read/Glob/Grep/ApplyPatch paths, permission path resolution, and environment observations. Workspace instruction discovery in an external linked checkout uses that checkout's root. Logical resource addresses such as work:// retain their own roots.

A directory selection is not a permission grant. Permission modes, rules, resource grants, protected paths, Plan ceilings, and sandbox writable roots stay owned by the shared session. Native operations on an external linked checkout still need ordinary resource authority. Confined Bash and local batch Eval require their cwd to lie within an existing configured writable root; additive path grants alone do not satisfy that existing cwd boundary. Selecting a checkout never adds a writable root. Unconfined execution remains subject to its ordinary explicit authorization and hard denies. The default role also inherits its delegator's context observations, frozen with the agent: a named delegator's own selection, or for a root child the root's workspace guidance, memory index, environment, tool listing, skills and resources. Neither inherits the root Goal or journal map. Without these observations the inherited system prompt would lack its changing parts, which arrive as context updates rather than system text.

The inherited default is the general-purpose agent for ordinary delegation: research, implementation, debugging, or mixed tasks. Callers select it by omitting role, not by passing a named general-purpose role. Named roles are specializations. Copying parent dialogue is a separate context choice and is not required to inherit capabilities.

Each chat buffer has its own role roster: its preset's :agents, or the parent's roster for a child. When a buffer offers Agent as a direct provider tool, its schema lists that roster's roles and model tiers in the buffer's own copy of the tool. The registered tool is shared and never edited, so sessions with different presets do not advertise each other's roles. A discoverable Agent is described by its ToolSearch contract instead.

Tool inheritance includes both native request tools and the delegator's effective specialist catalog for ToolSearch/ToolCall, including configured and MCP tools. Specialist identities are frozen as explicit category/name references. A nested default child inherits its immediate parent's catalog, not the root session's; an empty or request-restricted catalog does not grant additional tools. Named roles still resolve their own tool configuration. Retained follow-ups and cold restores reuse the frozen identities rather than the parent's current catalog; discovery and calls remain subject to current tool availability and permissions. Freezing retains specialists hidden only by the current Plan or Goal state; each invocation applies its own visibility. A later ordinary follow-up can therefore use the role's tools without retaining the preceding Plan turn's restriction. Skill capability restrictions still bound the frozen membership. Every agent receives a retained tool listing of its own callable specialists. Named roles get native SendMessage; a default child inherits its delegator's native tools and gets native SendMessage only when its inherited catalog permits SendMessage, so a request restriction never grants it.

context defaults to none, so the complete initial message is the child's sole assigned task and no parent dialogue is copied. Explicit all copies the complete effective parent conversation, and a positive decimal string such as "3" copies the anchored summary plus the three most recent live turns. Explicit summary freezes the realized parent transcript without the triggering Agent tool segment, runs one central handoff-summary request focused on the hook-accepted task, and stores the result as a labelled advisory Task background block before that authoritative task. The copy modes retain gptel's user/response/tool span properties, including actionable user instructions, and are taken from the current post-compaction buffer only. Callers use copied context only when the child must inspect parent dialogue and identify that dialogue as background in the initial task. Archived raw segments are never reconstructed. The initial task is appended after this immutable snapshot; parent turns added later are not synchronized into the child.

Before provider dispatch, after task preparation, mevedel materializes the role's dynamic instructions and effective tools, then captures the exact request backend, model, reasoning effort, system prompt, tools, context settings, request parameters, and model policy maps. Resolution starts with the delegator's current request defaults, applies the role workload, and finally applies explicit model and effort values. model accepts either a configured tier or BACKEND:MODEL; gptel validates the selected model's effort support. Follow-ups reuse this frozen configuration even if presets, role definitions, or parent settings change. Root-session permission rules and confinement preference remain live shared policy, not part of the frozen role configuration. An accepted implementation permission-mode override is inherited by the invocation that it starts, not saved as the retained agent's default; see permission propagation below.

Agent model metadata (:backend, :model and :effort names) describes what serves the child, never the delegator's or session's model. A nil effort means the provider default. Spawn reports a launch snapshot taken from the resolved frozen configuration. A running turn reports its invocation's effective configuration: a replaced gptel backend recovered by name, or the model and effort Claude Code acknowledged while preparing its ACP session. These corrections apply to the invocation's copy; the frozen identity is unchanged. Each turn's effective metadata is retained on the agent record and in the session sidecar, so idle and cold agents report the provider that last served them.

Children on every mevedel-admitted native gptel backend use the bounded sample recovery controller, with an independent allowance of 10 retries plus the initial attempt for each model sample. Backoff keeps the child active and its capacity slot reserved; the parent continues waiting and receives exactly one final RESULT. Recovery replays the prepared sample, not the invocation or completed tools, and retains the frozen model, effort, request identity and sample count. Attempt-local provisional output is discarded before replay. InterruptAgent, deadline expiry, buffer death and teardown cancel backoff, including when no transport is registered. Root abort does not automatically interrupt an independently retained child. Provider-reported usage from physical attempts is counted once; absent usage stays unknown. Claude Code/ACP stays separate and self-retrying; unadmitted background gptel retry policies are unchanged.

Claude Code selections dispatch through ACP using the frozen child model and instructions. Each canonical child path has its own native conversation reference, persisted before prompting, and follow-ups resume that reference. The ACP/MCP transport shares root streaming and tool projection; completion, interruption, capacity release and RESULT publication remain owned by the agent runtime. Child turns do not complete the root request or advance its turn count. A native child admits an ordinary request in its own conversation buffer for pipeline, permission and interaction ownership. Its invocation still owns native history and terminal publication; no gptel state machine is created. Interruption drains that request's cancellers and queued prompts, including while its parent is waiting. Final prompt usage is attached to the RESULT and charged to the owning Goal once. Adapter failures settle as errors; interrupted/failed native histories retain an uncertain marker. Follow-up recovery guidance requires the native user-message echo before tools continue. A lost turn restores as uncertain and requires acknowledged reconciliation before more tools.

When a child's native history is unavailable, the user can select its canonical path with M-x mevedel-claude-code-recover-history in the session. Recovery requires all turns to be idle and any active Goal paused. It preserves the retained agent record, frozen configuration and private transcript, and marks the next follow-up for an explicitly labelled excerpt continuation into a new native conversation. Root and sibling history are not included or detached.

Native children use the native context delivery contract. Queued mail is attached to the prompt after the native identity is persisted; mail arriving during a turn follows native tool batches, and duplicate or failed receipts cannot consume it. The child's frozen component selection defines both its system baseline and its compaction restoration. Its prompt collects the invocation's configured reminders without consuming the parent's reminders or hook context, and native compaction restores only that child's direct-child roster and learned path instructions. Continuation prompts keep the native ID, frozen configuration, current invocation and accumulated usage.

The root session retains every child's storage identity, path, activity, and transcript location after the turn settles. ListAgents returns the full path-sorted retained roster without storage IDs or transcript content. SendMessage continues an idle retained conversation or delivers mail to a running invocation at its next safe request boundary; later terminal results still go to the original spawn parent. Its collapsed disclosure contains the exact message and reports whether it was queued, started, or is waiting for a slot. Agent mail to /root can start an idle Background event turn; self-mail does not activate a turn. WaitAgent suspends its ordinary asynchronous tool callback until mail, user steering, or its bounded successful timeout wakes it. A MAIL wake-up is not sender completion; only the canonical RESULT is terminal. The wait registration is released before its callback resumes. A disconnected or erroring callback cannot leave the recipient stuck waiting or remove a new wait started by the callback. The triggering mail remains queued until ordinary conversation delivery acknowledges it; another WaitAgent observes that mail immediately even when the previous callback failed. InterruptAgent aborts one retained non-root agent's current turn by canonical path, returns its previous activity, and leaves its identity, conversation, mailbox, descendants, and future follow-up capability intact. The user can do the same from the view's background-work panel or cockpit (mevedel-agent-control-interrupt-user); the interrupted turn records the reason interrupted by user. For an idle agent it cancels any pending mail wake without discarding the unread mail.

Creation validates and freezes its inputs, privately reserves the canonical path and a tree-wide capacity slot, runs SubagentStart exactly once, then runs UserPromptSubmit for the initial task. The hook-accepted task is passed to dispatch without rerunning either hook. For summary, generation starts only after that final task exists; the parent row remains in Preparing summary context... until generation and durable child setup finish. The reservation is absent from ListAgents and path resolution until a durable transcript and provider FSM exist. Failure or parent cancellation releases it synchronously and suppresses late preparation callbacks. Every idle-agent follow-up runs UserPromptSubmit again but not SubagentStart. A blocked follow-up is not appended as a user turn; its additional hook context stays with that identity and is consumed once by its next accepted task. Every completed, errored, or interrupted turn runs one observational SubagentStop without removing the retained identity.

Each invocation aggregates only its own direct operating-system children. After those children are stopped or settled, noteworthy confinement facts are patched into the exact Agent row that started a new conversation or the exact idle SendMessage row that activated the retained turn immediately. Descendant agents, earlier turns, and steering messages sent to an already-running agent are excluded. The rollup uses hidden transcript render-data and is not added to agent sidecars or model-visible results.

The built-in role configurations are:

  • worker: broad implementation, execution, navigation, skill, task, and collaboration tools, with explicit concurrent-edit guidance
  • explorer: directly read-only investigation with authority to delegate to workers
  • verifier: adversarial read-only verification. Final reports must end with VERDICT: PASS, VERDICT: FAIL, or VERDICT: PARTIAL; the parsed verdict is stored in transcript render-data for the handle badge. PASS requires an adversarial probe, FAIL requires a concrete actionable defect, and PARTIAL is reserved for environmental limitations.
  • reviewer: retained leaf code-review agent used by /review. Reads diffs and surrounding code, then returns prioritized findings as JSON.

Child request defaults come from the parent, the selected role and mevedel’s model policy. There is no separate global child-agent preset layer.

The verifier's verdict-line contract does not apply to routine main-assistant or worker task summaries.

The frozen role prompt owns read-only judgment and the report contract. It is restored before each request, independently of transcript compaction; no every-turn reminder repeats it. Direct tool rosters and shared permission checks remain in force. Role names do not impose extra hidden reminder policy.

Every named role receives SendMessage and ListAgents. Possession of Agent grants transitive delegation authority and automatically supplies the complete Agent, WaitAgent, and InterruptAgent control bundle. Worker and explorer therefore orchestrate recursively; reviewer and verifier are communicating leaves without those control tools; their messages can still wake retained agents. The complete root-session tree shares the session's active-turn capacity (ten non-root turns by default), regardless of path depth. The root does not consume a slot, allowing eleven active agents in total. Waiting and human-blocked turns remain active and continue consuming their existing slot.

Before the first sample, the WAIT boundary injects only the caller's direct children as compact path and role references. Later WAIT boundaries add a child created in the same turn exactly once. Peers and deeper descendants are not injected; ListAgents is the explicit full-tree discovery surface.

A Goal runs in the root session conversation rather than through a special agent or phase machine. Child-agent turns are not Goal turns, but agents started from a Goal turn, nested agents included, charge their usage to that Goal as they work and receive its budget crossings (Goals). The RESULT's :usage field reports the settled request's usage. Each active root turn receives current Goal facts through retained context delivery, while the existing agent tree, capacity, and permission rules remain unchanged. Queued user messages steer the Goal before its next automatic continuation.

Each agent's :tools resolved via mevedel-tool-resolve-gptel at invocation time. Registered buffer-locally via mevedel-agents--specs per request (no caching). Each invocation gets a cloned reminder list with independent last-fired.

An optional :max-turns caps one Agent call's model samples. Every sample of the tool loop counts as one turn, however many tools it calls. At 80% the agent receives a one-shot warning to wrap up. The sample that reaches the cap tells the agent to answer now and ends its turn at the next tool boundary. If the agent still called tools, the call settles with its latest response followed by a [Stopped before a final answer: ...] note, so the caller can tell the report is incomplete. Retained follow-ups start a fresh count.

For Claude, the initial prompt prepares sample one. Each PostToolBatch hook either prepares the next sample or stops after the capped sample's tools have settled; a final text-only response is the sample its last boundary prepared. Warnings are turn events whose firing marks wait for exact SDK receipt; native compaction restores current limit guidance, including the final-sample notice, through the producer shared with gptel. A compaction that must wait for a continuation prompt has already spent a sample on the denied tool attempt or text-only response, so continuation reserves another within the same cap and delivers its warning; a spent cap ends the invocation without another prompt. This uses mevedel's existing sample definition rather than mapping the value to the SDK's tool-use-only maxTurns. Internal provider retries are not separately counted. A normal answer before the cap has no incomplete-result note.

The built-in agents set no cap, as in Claude Code, whose built-in agents also leave maxTurns unset; Codex has no agent turn limit. Their earlier caps (worker 50, explorer 30, verifier 20, reviewer 12) were never enforced. Telemetry from 238 agent runs in September 2026 showed medians of 12-22 samples, 90th percentiles of 34-51, and a maximum of 94, with about three tool calls per sample: enforcing the old caps would have cut about half of all verifier and reviewer runs, and no run approached a runaway bound worth setting by default.

Agent definitions may include :hooks using the same declarative hook shape as project hook files. These rules are scoped to invocations of that agent and are folded into the agent invocation layer before skill-scoped hook rules for fork skill invocations. Within an agent definition, Stop means "when this sub-agent stops" and is normalized to SubagentStop; top-level Stop remains reserved for the main assistant turn. SubagentStart :additional-context is auditable in both transcript surfaces: the parent Agent tool row records that hook context was supplied, and the child transcript stores the full hook context on the initial prompt.

Agent definitions declare an ordered :system-components list. Entries are registered prompt component symbols or inline (NAME :file PATH) / (NAME :text STRING) components. Every agent profile is workspace-aware, so workspace-config and environment must be present explicitly. There are no per-section inclusion flags and no automatic skills inference: selecting memory or skills is part of the role definition.

The built-ins all receive scoped AGENTS.md / AGENTS.local.md and environment context without inheriting the main coding-assistant role. Worker also receives memory; Explorer, verifier, and reviewer do not. Worker and Explorer select the active skills roster and expose Skill / ListSkills; verifier and reviewer remain skill-free. Worker, Explorer, and verifier share the reporting tone, while reviewer relies on its strict output contract.

Asynchronous agent lifecycle

sequenceDiagram
    participant P as Spawn parent
    participant H as Agent runtime
    participant C as Retained child
    P->>H: Agent request
    H->>H: Reserve path and prepare the accepted task
    Note over P,H: Setup failure releases the reservation and returns an error
    H->>C: Persist transcript and start request
    H-->>P: Canonical child path
    Note over P,C: Parent and child continue independently
    C->>H: Turn settles
    H->>H: Stop hook, release capacity, retain conversation
    H-->>P: Queue terminal RESULT; wake an existing waiter or offer an idle root wake

The diagram covers initial spawning and settlement. Follow-ups reuse the retained identity and configuration, run UserPromptSubmit for an idle agent's new task, and do not rerun SubagentStart. Tool counts, activity and response refresh belong to the current invocation in that retained conversation. An invocation keeps only its latest few activity items. Settlement drops the retained buffer's last request payload and audit decoding memo: an idle agent otherwise kept about as much Lisp data alive as its transcript, and a continuation builds a fresh request. A caller that needs to wait within its current turn invokes WaitAgent; a caller may instead finish while descendants keep running. An ordinary terminal result to /root can then start a Background event turn; a non-root parent stays idle until explicitly followed up. /review, /verify, and fork-skill workflows may keep their owning interaction open until a leaf result arrives, but that awaiting behavior does not create another agent execution mode.

Agent resource results

Each retained registry record keeps the complete latest settled payload and its terminal outcome (completed, errored, or interrupted) separately from the bounded inline RESULT mailbox preview. The complete payload is recorded before the preview is published, including recovery settlements. Request and owned-execution teardown must both succeed before terminal state is published. PID-lock settlement commits the idle record and queued result before delivery; portable settlement -- every project session, local target included -- publishes transcript plus sidecar atomically before it wakes a waiter or invokes a workflow result handler. Authority, not target locality, chooses: a portable session resolves its transcripts through the publication, so a direct write would leave resume unable to see them. A new or follow-up turn clears the previous settled result before it becomes active, including the starting interval in which provider setup can yield to other mailbox publications. Failed or quit follow-up dispatch restores the previous result without discarding mail delivered during setup. Active agents expose no streaming or stale result and are reported as not ready. A later idle turn replaces the retained result atomically.

agent://root/PATH reads that complete settled payload and history://root/PATH reads the same retained identity's transcript through the shared read-only resource-address resolver. Neither address changes the conversation, mailbox, transcript, or settlement state. The canonical path, not the registry's opaque storage identity, is the only addressable identity. history://root uses the same projection for the main agent's current conversation, including unsaved transcript content. It resolves the owning session's root data buffer even when called by a retained agent, and appears in history listings and completion without requiring a child agent. Both history forms support the existing Read pagination and concise tool results; neither traverses pre-compaction archives or supports search. Root history requires a live root buffer, including one restored by normal session resume; the read itself never resumes a session. See address-to-resource.md.

Interrupting retained agent turns

InterruptAgent(target) resolves only canonical or relative retained paths. It rejects /root, the caller itself, malformed paths, unknown paths, and opaque storage ids. An idle target is a successful no-op. An active target's provider request or requestless wait is aborted, its transcript is finalized as aborted, its active-turn slot is released, and exactly one canonical RESULT with outcome interrupted goes to the stable spawn parent. The payload includes the interruption reason, bounded useful partial work when available, and the saved transcript path when available. Request teardown cancels the active tool pipeline, terminates the target's child executions, and prevents its queued execution work from being admitted after the turn becomes terminal. Native ACP interruption waits for its bounded terminal acknowledgement before settling the retained turn, so its final usage remains accountable. The runtime canceller returns deferred while it owns that acknowledgement; killing the owning buffer still closes the connection immediately.

Interruption never recurses. Descendant turns continue, and the target's path, conversation buffer, mailbox, and registry record remain retained. A later SendMessage therefore continues the same conversation. An interrupt request clears existing wake marks without discarding unread mail; messages sent after the request can wake the agent again. Interrupt-versus- settlement races use the ordinary exactly-once settlement gate: whichever terminal event wins is the only RESULT. The tool result itself contains only the target's activity observed before the request and renders Interrupted PATH from the canonical event.

Inter-agent messaging (SendMessage)

SendMessage(target, message) resolves canonical or relative retained paths tree-wide. An idle non-root recipient starts a turn with the message as its task. For an active recipient, or at capacity, it queues one canonical MAIL record containing type, sender path, recipient path, and payload. Agent mail to /root can wake the idle root; self-mail never starts a turn. Successful sends return an empty result, except when capacity delays activation: then the result says the agent starts when a slot frees. A collapsed SendMessage: PATH disclosure reports message queued, started, or waiting for a slot; its path opens the retained transcript and its body holds the sent message. Canonical MAIL payloads are retained in full without a mailbox body cap. Since delivery may cross a root-turn boundary, an agent should put its final verdict in its terminal response rather than treating SendMessage as its completion channel.

Mailbox append is an acknowledged durable mutation. Once the session has a storage path, mevedel rolls back a failed append and reports the send as failed; it releases a matching WaitAgent only after the root session snapshot has committed. Idle-root wake eligibility likewise follows durable publication.

Before a recipient's next model sample, its retained unread queue drains in FIFO order. Each record is injected as a separate user-role communication block and written to the retained conversation transcript before the unread record is removed. Mail for an active agent is delivered at its next ordinary WAIT boundary, without interrupting an in-flight response, tool call, or prompt. The tool result never duplicates the message body.

After a non-root settlement ends, the harness offers idle recipients with waking mail a turn, oldest waking mail first while capacity allows. MAIL and ordinary RESULT from another sender wake non-root recipients, including results delivered to an idle spawn parent and mail arriving during a final response. Workflow-consumed results and EXECUTION records do not wake them. Preparation cancellation and failed-start rollback also reoffer capacity waits. While a settlement in the session runs, no retained agent starts, even with free capacity: the settling agent already reads idle, but its RESULT may still roll back. A send in that window reports waiting for a slot, and the offer that follows every settlement, committed or not, starts the agent. Releasing a finished invocation's request data never touches a newer turn in that buffer. New turns use current session permissions and sticky Plan state; unread MAIL from a Plan sender additionally stamps any turn that will read it as read-only, including one started by a later direct assignment. RESULT records do not carry the sender's Plan stamp.

Agent-originated MAIL and ordinary terminal RESULT records addressed to /root use the same idle Background event scheduler as Monitor and root-owned Bash completions. This is a background notification, not a user instruction or a new grant of authority. Queued user follow-ups run first, background events next, and Goal continuation last. The same holds apply: a composer draft, pending interactions, or a held follow-up drain prevents the wake, and dispatch uses current root permissions. Active WaitAgent delivery is unchanged and does not create a second root turn.

Wake marks are runtime-only; unread mail remains durable. Restarted sessions read restored mail at the next ordinary turn, and recovery-generated results do not start background turns. Successful root turns reoffer eligible unread mail that arrived too late for their last sample. Failed or aborted root turns do not automatically retry that mail in a wake loop; it remains available for a later turn. Non-root errored settlement clears that recipient's wake marks too; interruption clears marks when requested, so later MAIL or RESULT can start new work. In particular, a child's result arriving after its parent's interruption wakes that parent again.

WaitAgent(timeout_ms?) is a wake primitive over the caller's mailbox, not a message transport. Its ordinary asynchronous callback stays pending without a model sample and without releasing the caller's active-turn slot. Existing or new mail releases it immediately. New root user input becomes a separate user-role steering message in the same resumed request, so no intermediate model sample can run before the input is visible. The default timeout is 30,000 ms. Out-of-range numeric tool arguments clamp to 10,000-3,600,000 ms; unrepairable tool arguments are rejected, and timeout is a successful outcome. Its result contains only the wake reason. The view renders Waiting for agents while the tool is pending. Settled waits render WaitAgent: agents (OUTCOME); consecutive calls coalesce into the final row with a count while every canonical call remains in the transcript.

Independently completed yielded Bash executions use the session or invocation object captured for their fixed owner when Bash starts. A retained invocation holds its terminal response while an owned execution is live. A completion that arrives while the agent still works goes to the agent's own mailbox, read at its next provider request as for the root. Settlement publishes the unchanged final answer as RESULT, and each completion the agent could not read (arrived after its answer or still unread) as a separate EXECUTION record to the spawn parent, attributed to the agent. These records commit together; workflow result handlers consume only the RESULT. A child's Bash completion does not wake WaitAgent before settlement or itself start a model request; the ordinary terminal RESULT to a root spawn parent can wake the root.

The root's own completions differ: a root EXECUTION record from a command that ended on its own, and a root MONITOR event batch or terminal notice from the Monitor tool, also start an idle root turn, as described under terminal delivery in tools. A stopped execution's record, and records whose result WriteStdin or StopExecution already returned, are delivered without waking. Like any root mail they release an active root WaitAgent. A MONITOR record carries its execution_id and the monitor's description; the model receives it as <agent-message type="MONITOR" sender="/root" recipient="/root" execution_id="..." description="..."> with the description XML-escaped (a terminal notice uses MONITOR_TERMINAL with event_count, termination, outcome, exit_code; an EXECUTION record's opening tag carries execution_id, description, command, termination, outcome, exit_code, so views read opener attributes, never the payload), and the view shows it as a Monitor: DESCRIPTION card. The transcript parser treats it like other agent mail, never as user input. Records are saved with the session; their wake mark is runtime state and is dropped, so after a restart unread records reach the model at its next turn without waking it.

Review and verify commands

mevedel-review / /review and mevedel-verify / /verify run dedicated asynchronous leaf-agent turns. They share a target picker for uncommitted changes, diff against a base branch merge-base, a specific commit, the last commit, or custom instructions. Unlike ordinary user skills, this path is first-class: it ignores user/project skills named review, creates a context-isolated retained agent at a unique path such as /root/review or /root/verify_2, and shares target CAPF for explicit target forms such as current, HEAD, branch:<name>, and commit:<rev>.

Git evidence packages are prepared after the accepted command returns, one section per callback. Aborting the request or killing its source buffer cancels preparation and removes the unfinished package before any agent is dispatched. Git commands still run individually and synchronously; a very large diff or a slow remote command can exceed the normal callback budget.

The owning workflow attaches a one-shot consumer before provider dispatch and awaits that leaf's ordinary terminal RESULT. Settlement first queues the canonical envelope in parent mail; after successful workflow delivery, the consumer removes that exact envelope so a later model turn cannot receive a duplicate or wake the root for an already-consumed result. Handler failure leaves the queued result for ordinary mailbox delivery, including an idle-root background wake. Completion therefore uses the same settlement and active-turn accounting as every other asynchronous agent. Cancellation interrupts only the active turn: the canonical agent path and conversation remain retained for inspection or follow-up.

/review dispatches the reviewer agent and parses its Codex-style JSON finding shape: findings, overall_correctness, overall_explanation, and overall_confidence_score. Finding priority accepts integers 0–3 or JSON null; null and omission both mean unspecified. mevedel renders a readable summary as the assistant reply and stores a synthetic review <user_action> in the parent transcript so later turns can refer to numbered findings. The view buffer strips that synthetic block from normal display. Schema-invalid JSON falls back to the raw reviewer output and still settles the parent turn.

/verify dispatches the verifier agent with verifier-oriented wording: inspect adversarially, run or recommend relevant checks when allowed, and finish with the verifier prompt's VERDICT: PASS, VERDICT: FAIL, or VERDICT: PARTIAL line. The workflow accepts only one exact final verdict, read from the complete settled report rather than the bounded preview; malformed reports remain visible but are marked rejected.

Goal completion uses the same verifier role and verdict contract, but selects its model and effort through goal-review (default tier: strong). /verify and ordinary verifier agents retain the verifier workload. The Goal check receives the exact objective and any accepted plan with context: none, so it discovers evidence independently of the implementation conversation.

While either task runs, the parent view shows an inline Review or Verify handle backed by transcript metadata. The handle updates with running/done/error state and recent tool-call counts like other agent handles, without exposing the hidden bookkeeping block to the model.

Transcript persistence and views

Each retained agent runs in its own gptel conversation buffer backed by a canonical transcript under the root session's agents/ directory. The buffer's default-directory remains the session working directory (falling back to the workspace root), including after transcript attachment and cold hydration; transcript storage location never becomes tool cwd. The sidecar persists an explicit registry record for its canonical and parent paths, role and frozen configuration, activity, unread mailbox, pending conversation-local hook context, conversation location, and internal storage identity, plus the latest settled payload and terminal outcome when present.

Cold restore resolves missing mevedel built-in tools through their owning registrars before decoding the frozen roster. This does not substitute unknown tools or search other categories. Claude root and retained-child conversations resume their separate native references after an editor restart; restored child model selection remains frozen even when the parent model changes. Resume derives an idle turn's transcript status from that durable outcome rather than from activity alone, so an agent that failed or was interrupted does not come back reading as one that finished, and a settled turn with no recorded outcome reads as incomplete rather than complete. The canonical path is the only model-facing address; storage identities never enter collaboration tools or resource addresses. The mailbox remains a bounded delivery preview rather than the source of truth for an agent result. The frozen configuration is authoritative for the agent's request setup, so agent transcripts omit all of gptel's request-config Org properties while retaining GPTEL_BOUNDS. Initial task text is saved after installing the frozen configuration; provider setup does not force a second save of the same transcript. In materialized portable sessions, a new transcript and its dirty metadata share one strict publication through the session's root buffer, including for nested agents. Registry admission remains a separate acknowledged commit.

Terminal settlement publishes the result before delivery. After that commit, gptel's post-response hooks may add transcript text; their extra checkpoint uses the existing debounced conversation save instead of extending the terminal callback. If settlement is still pending, that checkpoint remains synchronous. Explicit saves and teardown flush the pending checkpoint normally. Generated task background is ordinary persisted conversation context with its own structural type. Follow-ups and agent compaction therefore absorb it naturally without replaying or regenerating it.

Resume validates the registry, configuration and transcript locations without loading idle conversations. The first SendMessage activation, history resource read, or Emacs transcript inspection hydrates only the selected identity through the same verified artifact resolver. Unread mail and pending hook context remain in the registry until their ordinary delivery boundary. Active abandoned turns still hydrate during resume so recovery can retain their partial responses. Failure to load a deferred conversation is reported at access before provider dispatch.

Inspection keeps the resolver's read-only/no-save marker after major-mode setup. A later owned follow-up loads a writable conversation rather than writing through an inspection snapshot. Browser inspection queues hydration of the selected retained conversation outside the guest frame handler; the handler itself never performs cold target reads.

The registry stores each conversation location as a session-relative path. For a remote session, cold hydration, terminal inspection, recovery links, and compaction resolve that logical path through the session's staged or captured publication and verify its digest; a materialized fixed-path cache is never read as authority. The conversation buffer still visits the qualified logical path, so immutable publication filenames never reach tools, prompts, or views.

mevedel-agent-conversation.el owns conversation creation and hydration, frozen request-local installation, activity snapshots, response extraction, and transcript saves. Native Emacs auto-save also checkpoints modified retained conversations, as does the in-flight checkpoint timer while any request runs, so an unattended agent turn reaches disk before it settles. Emacs exit flushes their text and pending transcript timers before root session ownership is released. mevedel-agent-exec.el is the provider adapter: it owns the gptel request FSM, prompt dispatch, and streaming callback contract. It consumes its exactly-once terminal latch only after runtime settlement accepts the handoff; transformer or transcript-extraction failures become structured terminal errors, while a rejected runtime handoff remains pending for retry. Frozen request locals use one closed symbol schema owned by mevedel-agents.el. Durable configurations contain every schema entry exactly once, and hydration rejects unknown, duplicate, or missing keys before it changes a conversation buffer.

Persisted agents may compact older history immediately before a continuation request. The canonical transcript path remains stable, the original task and recent tail remain visible, and later compactions update the existing anchored summary instead of stacking summaries. Each rewrite first creates the next numbered compact-NNNN sibling as a recovery artifact. Those siblings are not agent handles or sidecar entries; they belong only to the original session and are not copied by Session Forks. Each retained conversation owns this lifecycle independently; compacting one agent does not change its registry path or any other conversation.

Session Forks copy eligible canonical transcript files and metadata only as historical inspection artifacts. They do not copy registry identities, frozen configuration, mailboxes, waiters, or active turns. Historical agent transcripts remain openable from their handles but are absent from the collaboration roster, and their former canonical task names are immediately available to the child. Rewind creates no child: it clears the current session's live agent ownership.

mevedel-view-agent.el owns transcript lookup and inspection views plus the live-agent status rows and targeted handle refresh. The main view renders compact one-line agent handles from tool render-data and sidecar state. Handles show canonical path, role, status, call count, and transcript attribution; recent ephemeral activity is kept out of the default view to avoid churn. Resident retained agents open a rendered read-only view over their conversation buffer whether running or idle; cold and historical handles use the saved transcript file. Open live transcript views are observation-only projections that follow the main renderer's stream and tool cadence without redirecting parent interactions. See docs/view.md for their update, scrolling, header, settlement, and failure-isolation contract.

The agent view owner supplies running, waiting, or blocked rows to the view's background-work panel, beside live commands and monitors, so the user can locate and control active agents without scanning the whole transcript. Terminal agent outcomes stay in their inline tool handles, transcript views, and result notices instead of being repeated in the panel.

Permission and confinement propagation

Every nested agent shares the root session's direct rules, explicit denies, protected resources, resource grants, and confinement preference by reference. Its permission mode follows the live root baseline unless its spawning request or parent invocation carries an accepted implementation override. That override stays with the invocation and its descendants even after the root turn settles; an idle follow-up inherits the caller's current override rather than the previous invocation's. Explicit denies and immutable Plan restrictions still apply. Required decisions and direct interactions are attributed with the requester's canonical path and rendered in the root view's shared queues; child transcript views remain inspection-only. A turn blocked on either queue remains active and consumes tree capacity. Interrupting that turn cancels only its own queued entries.

The retained-agent tree shares the root session's work:// namespace, with session-owned work://plans/ and workspace-owned work://shared/ for notes, findings and handoffs across sessions. Standalone/sticky Plan mode keeps session-only ApplyPatch available to retained agents. It rejects any ordinary, shared, memory, or bare endpoint before local materialization, including mixed local/ordinary and ordinary-only calls, while other edit tools and Eval remain unavailable.

Every agent turn started under Plan carries immutable Plan read-only authority: directive planning stamps its root request, and a spawn or follow-up made while sticky Plan is active stamps the new invocation. The stamp is copied into every nested invocation and request, including forked skills and their preparation. Those turns keep Plan tool and Bash restrictions after the root workflow advances to approval or implementation, or the user leaves Plan; mutable session phase is not an authority boundary. Unlike standalone/sticky Plan mode, directive Planning denies ApplyPatch, including session-only proposals, to its requests and retained agents. Eval is unavailable in both.

A caller with Plan authority cannot direct a turn that lacks it. SendMessage to an active agent requires the target's current turn to be Plan read-only; SendMessage to /root is always accepted. SendMessage to an idle agent starts a stamped turn, immediately or when capacity frees. Any activation reading unread Plan-sender mail retains its stamp. See Plan mode.

Delegated invocation/request rules may narrow authority and may allow ordinary known-safe commands, but they cannot authorize dangerous or complex Bash, live Eval, protected resources, or full execution escalation. An ordinary sub-agent may request additive or full authority only through the same user-visible queue; there is no separate model-visible access-request tool. The main view's agent row retains durable warnings for materially non-default child access. Additional read-only mounts stay silent. Each Bash or batch-Eval result records the boundary used by that call, and the agent transcript identifies the affected tool.

Task status

Tasks are tracked per caller (/root and each retained agent path). Agent-owned tasks and status notes use the retained agent's canonical path for automatic assignment, grouping, rendering, and terminal finalization; opaque storage IDs never enter the task surface. Explicit canonical owners must name a retained agent in the session, while /root normalizes to the main owner. Explicit non-path owner strings remain available as user-defined task buckets. Task IDs are allocated across the entire session, including completed tasks, not separately per caller. Omit id to create work; an existing ID always means an update. An agent may update tasks and notes owned by itself or descendants, not another retained agent. Root may manage every owner; Main and non-path buckets stay shared labels. A foreign-agent update rejects the entire TaskWrite batch before any task or note changes. Explicit creation for another owner and reassignment by an authorized writer remain allowed attribution changes, not agent dispatch. Once transferred, a task is protected by its new owner. Successful agent settlement (including a turn returning to retained idle) completes that owner's open tasks, clears its note and unblocks dependents. Failed or interrupted turns leave tasks open for recovery, not falsely completed. Resume validates persisted task and status-note owners against the restored registry and drops entries carrying opaque IDs, malformed paths, or unknown canonical paths before they can reach model-visible task state. blockedBy is the only dependency edge. Every task write drops the edges it resolved: an edge to a task that is absent or already completed is removed, so neither a task created blocked by finished work nor a resume can leave a surviving task blocked by something that will never clear. Tasks therefore remain stable across follow-ups and cold session resume.

The task status fragment is compact and appears only while at least one task is open. Open tasks are ordered once by display priority -- in progress, then pending, then blocked -- and the separator rule carries the session tallies (tasks · 3 running · 1 blocked · 6 done), so each count is stated once rather than per owner. An owner holding a single open task renders inline behind a dim owner label with the /root/ prefix stripped; an owner holding several renders under one dim header placed at its best-ordered task, which keeps that owner's rows adjacent. A running agent-owned row shows its activeForm in place of its subject. TAB or RET on the fragment toggles completed task details, which render in a single done section, each row keeping its owner attribution. The fragment caps itself against the live window height; when rows are omitted, it keeps a stable prefix with open rows ahead of completed rows and reserves one final count row such as ... 4 completed, dropping any header left with nothing under it. A subject is stored as one non-blank line: whitespace runs collapse to a single space and a blank subject is rejected. Completed tasks are not pruned from the session task list.

The task nudge reminder does not reuse this rendering. It sends the model the same shape TaskList returns, with canonical owner paths and unabbreviated subjects, so display decisions cannot alter what the model reads. It identifies canonical child owners as retained agents' work rather than the root caller's work, and fires at most once per stale interval (eight turns by default), not on every request after the first stale write.

Each owner group can also carry a short status note through the top-level note/noteOwner arguments of TaskWrite, which may carry only a note. TaskWrite validates every task entry and the note owner before changing anything, so an invalid entry or unknown note owner rejects the whole call; no task is created or updated. Notes render under the owner's header, or under its single inline row; the main session's note opens the panel, having no header to hang from. A note is dropped from view when that owner has no open tasks, so a completed-only task list does not keep the overlay visible.

Model tiers

mevedel-models.el resolves the current session's preset-local named tiers and workload map. A tier can select a concrete gptel provider and reasoning effort; a workload can select a tier or exact provider and override effort. Resolution starts from the session backend/model/effort, then applies tier and workload values, followed by explicit Agent policy or the policy of a skill that owns the child request. Explicit Agent model and effort values have final precedence. Skill-specific preset entries use $skill-name symbols in the same workload map. Agent buffers receive a deep-copied snapshot of the maps, so nested agents keep the policy in effect when they were launched.