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.mdwith /workspace/changes.md. Give it both paths and ask for unsupported claims,missing changes, and uncertainties. Wait for its result. Check its findingsagainst 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. |