Skip to content

Using Lightspeed

Sub-agents and federation

An agent can split a task into work for specialists, or send an event to another bot with its own ongoing job. Lightspeed provides separate mechanisms for those relationships because they have different ownership and lifetimes.

A sub-agent is a child session created for a bounded task. It uses an allowed profile, returns one result, and closes. Bot federation sends a durable event to an independently configured bot in the same universe. That bot owns its inbox, routing, conversations, and future work.

Need Use
Review a draft and return findings to the current task A sub-agent.
Run several independent checks and combine their results Multiple sub-agents, with joined calls or promises.
Notify an ongoing release bot that a review is ready A federation event.
Ask another bot to handle work on its own schedule and report later Federation with a requested reply receipt.

Enable sub-agents in the parent profile, and bot messaging in the sending and receiving bots’ settings. Use an Operator or Admin account to configure them. These settings determine the agent’s tools; Agent and tool access explains the runtime boundaries.

Delegate a release review

First create the release-reviewer profile from Profiles and instructions. It should have a clear description and its own read-only attachment to the release-notes workspace at /workspace.

Open the parent release-editor profile and enable Sub-agents. In Agents, select release-reviewer. Optional limits are hidden by default; choose Customize limits to edit them. Set small limits for this task, for example Max depth 1, Max descendants 8, Max concurrent 2, and Deadline (ms) 300000. Save and start a new session from the parent profile, or apply it to an existing idle session.

Ask the parent:

Ask the release-reviewer sub-agent to compare /workspace/release-notes.md
with /workspace/changes.md. Give it both paths and ask for unsupported claims,
missing changes, and uncertainties. Wait for its result. Check its findings
against the files, then report the changes you recommend. Do not edit yet.

The child receives the supplied brief and its own profile. It does not receive the parent’s conversation or inherit its tool grants. Include the facts, paths, and expected result the child needs in the brief. In this example, both profiles attach the same workspace, so both agents can read the files without copying them into the child conversation.

Inspect the parent’s tool activity and follow the Sub-agents link to the child transcript. A completed child should show its own reads and review; the parent should use that result in its answer. To find finished children in the session list, open Filter sessions → Include and select Sub-agent sessions and Closed sessions.

Understand the child boundary

The child runs with the selected profile’s full grants. Allowing a profile that can write to a database delegates that authority even if the parent cannot call the database tool directly. Review the child profile as part of the parent’s access design.

Attaching the same live workspace lets both agents see the same files. Give a reviewer Read only access, or use a snapshot when it must review a fixed version while another agent continues editing.

The child can use its own attached machine or share its parent’s. The child profile’s Inherit parent environment attachment resolves to the parent’s active machine when the child is spawned, with the child attachment’s chosen access. If the parent has no active machine, that attachment is omitted. Sharing a machine shares its filesystem and process credentials. See Environments.

A sub-agent spawned by a bot does not become another bot. It gets its profile and brief, without the parent’s bot history, inbox, or controller-specific tools.

Join a result or use a promise

The parent uses agent_run for a result returned with the tool call. Several calls in the same model turn can run concurrently and return together. For work that can proceed alongside other parent activity, agent_spawn returns a promise: a handle the parent can await later.

Both calls accept the same model-facing arguments. For example:

{
"agent": "release-reviewer",
"input": "Compare /workspace/release-notes.md with /workspace/changes.md. Report unsupported claims, omitted changes, and uncertainty. Do not edit files.",
"label": "Review Acorn release notes"
}

For a spawned task, the parent passes returned promise IDs to await:

{
"promises": ["promise_1"],
"mode": "all",
"timeout_ms": 300000
}

Use the actual returned ID. mode: "any" resumes when any listed promise is ready. An await timeout stops waiting for that interval; it does not cancel the child. cancel requests cancellation through the promise and closes the child session.

Pending spawned work normally belongs to the parent run and is canceled when that run ends. detach promotes a promise to session lifetime when work must survive that boundary. The session then owns that outstanding work until it finishes or is canceled; force-closing the session cancels it.

The result includes a status such as completed, failed, cancelled, or deadline, plus output or error information and the child session ID. Check the status before treating the output as a completed review. Images and documents referenced in the child’s answer can also pass back to the parent. A child returns one run’s result and closes automatically. Delegate a new task when more work is needed.

Return file attachments

A child can deliver a file even when its parent cannot access the child’s workspace. Ask it to save the deliverable, call vfs_reference, and cite the returned file: link in its successful final answer. Both joined agent_run results and spawned/awaited results carry descriptors for the known attachments referenced in that answer. Intermediate files that are not cited stay with the child. A parent handing the result to its own parent follows the same rule.

The descriptor identifies immutable bytes. A later workspace edit or deletion does not retarget the attachment, and the receiving session retains the referenced content. A digest written only in prose does not establish an attachment or keep its bytes alive. Access to downloads still follows the universe’s blob permissions.

Image and PDF media use the existing media: links and native-media admission rules. File references preserve a downloadable attachment without loading it as model input. Either [label](file:HANDLE) or image Markdown for a returned image handle can select an attachment for handoff. See Workspaces and skills for creating references and capturing outputs from a machine.

Bound the delegation tree

The default limits are depth 2, 16 total descendants, 4 concurrent open descendants, and a one-hour deadline per child. The deadline ceiling is 24 hours. Configure smaller values when a task should be quick and shallow.

These limits apply across the root’s delegation tree. Max descendants counts every child created during the tree’s lifetime; finishing a child does not return that capacity. Max concurrent limits children still open. Further delegation can narrow the inherited limits but cannot widen them.

The child records its profile revision, parent, and root, so its execution can be inspected against the setup it received. Changing the saved profile does not rewrite a child already running.

Connect two independent bots

Suppose release-watch should ask a separate review bot for help. Create a bot with ID release-reviewer using the shared profile of the same name, following Bots and triggers. The bot and profile are different records even when their IDs match. Give the bot a brief describing how to review incoming requests and resolve their events with findings.

Open release-watch and choose Settings → Other bots. Enable Can message other bots and save. Review Accepts messages from at the same time; enabling sending can also open an otherwise disabled inbox.

On the receiving release-reviewer bot, set Accepts messages from → Only these bots, select release-watch, and save. Nobody disables acceptance; Any bot here accepts senders in this universe. The recipient owns its inbox’s Routing & batching… settings. Keep queue delivery for a review that needs its own completed run.

Give each bot a useful description. The sender’s directory lists enabled bots in the same universe whose inboxes accept it. Sending permission takes effect at the sender’s next idle boundary; receiving policy applies to the next event.

Send a test event to release-watch asking it to request a review from release-reviewer and request a reply. Its bot_emit tool can submit:

{
"to": "release-reviewer",
"kind": "release.review",
"summary": "Review the Acorn 1.2 release notes against the change list.",
"data": {
"changes": "/workspace/changes.md",
"notes": "/workspace/release-notes.md"
},
"reply": true
}

The receiving profile must independently have access to those paths. Event data supplies references and facts; it does not mount the sender’s files or grant its capabilities.

Follow admission and replies

bot_emit returns the destination bot and admitted event sequence number. That means the recipient accepted the event, not that the review finished. Inspect the recipient’s Activity and the conversation that handled the event to follow its work.

With reply: true, the controller can later send a bot.reply receipt to the original logical sender conversation. The receipt is correlated by bot and event sequence. The recipient should resolve the event with a useful outcome and summary; the sender handles that later receipt as another event. There is no cross-bot promise to await like a sub-agent result. When the sender’s current event depends on that reply, it can resolve the event as deferred and handle bot.reply in a later run. Deferral itself does not schedule a retry.

Receipts follow the recipient’s delivery semantics. Append or steer delivery can acknowledge that disposition rather than a completed answer. Receipts can also be skipped when the requester is disabled or closed, or the hop limit is reached. Design the bot’s brief to handle missing or deferred replies without claiming the requested work completed.

Federation is confined to one universe. Rate limits and an eight-hop ceiling bound chains between bots. A send can be refused because the target is unavailable, has no accepting inbox, filters the event, or reaches a rate or loop limit. Messaging permission does not let one bot create or configure its neighbors.

If delegated work is missing

Symptom What to check
The parent cannot find a specialist Add the named profile to Sub-agents → Agents and give it a useful description.
The child cannot read the parent’s files Link the workspace in the child profile; the brief alone grants no access.
New children are refused despite none currently running Check the lifetime descendant budget as well as concurrency and depth.
A spawned child ends before its result is used The parent run may have ended with a run-scoped promise still pending. Await it or deliberately detach it.
A bot is absent from the federation directory Check sending permission, target state, and the recipient’s enabled inbox allowlist.
A send succeeded but there is no answer Admission and completion are separate. Inspect receiver delivery, outcome, pause/budget state, and requested-reply limits.