Working together¶
Agents are separate by default and cannot reach each other at all. When you want two of them to work together, you open a channel between them by hand — and choose what that channel is for. Only that ever crosses.
Nothing else changes. Each agent still works in its own space, at its own autonomy level, with its own memory, secrets and skills. A channel does not merge two agents; it carries one specific kind of thing between them, and you can withdraw it.
What a connection is¶
Three properties do most of the work, and they are worth having straight before you open one.
It is one-way. connect writer researcher lets writer hand work to
researcher. It does not let researcher hand work back. If you want that too, open
the reverse connection.
It is for one thing. A channel opened to hand over results is not a channel to read what the other agent knows. Each mode is its own permission, so opening one never quietly grants another — and asking over the wrong one is refused, even between two agents you have already connected.
Withdrawing it is final. disconnect closes a channel for good. Connecting the
two agents again opens a new channel; it does not restore the old one, and anything
handed over on the old one stays out of reach.
The five modes¶
A mode answers one question: how much of the other agent comes back?
| Mode | What crosses | The command that uses it |
|---|---|---|
handoff |
its final answer, and nothing behind it | asterism handoff |
artifact-only |
a list of the files it made — not its words, not the contents | asterism artifact |
read-summary |
a short, screened extract of what it has learned | asterism summary |
shared-brief |
nothing comes back — this one carries context in | asterism brief |
delegated-tool |
the answer from one tool it owns, run by it, credentials and all | asterism call |
Whatever the mode, these never cross: the other agent's memory records, its secrets, its tools, its working notes, and its transcript — how it got to the answer. You get the thing the mode names, and nothing behind it.
A walkthrough¶
Two agents: writer, which drafts, and researcher, which digs through source
material. Every command below runs, and every response is what asterism prints — only
the agents' own words, which come from whichever model you configure, will differ.
$ asterism new writer --soul casual-helper --role "drafts and tightens blog posts" --trust autonomous
Created agent "writer" (autonomous) — soul: casual-helper
role: drafts and tightens blog posts
workspace: /Users/you/work/.asterism/agents/writer
$ asterism new researcher --soul careful-consultant --role "digs through source material" --trust notify
Created agent "researcher" (notify) — soul: careful-consultant
role: digs through source material
workspace: /Users/you/work/.asterism/agents/researcher
Note the two different autonomy levels. They stay that way — that matters below.
handoff — hand over a task¶
Right now these two agents have no path between them at all, so there is nothing to refuse:
$ asterism handoff writer researcher "summarize the Q3 deck"
No active handoff connection from writer to researcher. Open one first: asterism connect writer researcher --mode handoff
Open the channel, then use it:
$ asterism connect writer researcher --mode handoff
Connected writer → researcher (handoff). Use it with: asterism handoff writer researcher "<task>"
$ asterism handoff writer researcher "summarize what the Q3 deck says about pricing"
The deck holds enterprise pricing flat and moves the team tier up 12%.
researcher did that work as itself — in its own workspace, framed by its own
memory and skills, at its own autonomy level. What came back is its final answer.
writer did not see its memory, its files, or how it got there.
That last point is the one worth being precise about, because it is the obvious thing
to worry about: a handoff is not a way around another agent's limits. The work
runs under the receiving agent's autonomy, so a destructive action answers to
researcher's own gate and to nothing writer has — no matter how much autonomy
writer was given. Confirm it on the agent that paused:
asterism confirm researcher <run>
artifact-only — get the files, not the words¶
Sometimes you want the thing an agent made, not its account of making it.
$ asterism connect writer researcher --mode artifact-only
Connected writer → researcher (artifact-only). Use it with: asterism artifact writer researcher "<task>"
$ asterism artifact writer researcher "draft the market section"
Actions (1 executed):
✓ executed fs.write (write)
researcher produced 1 artifact:
drafts/market-section.md 55 B
Only these references crossed — not researcher's words, memory, or the file contents.
The files are in researcher's own workspace.
You get each file's path and size. You do not get the contents — the files sit in
researcher's own workspace, on your machine, where you can read them yourself.
To bring one across into writer's workspace, fetch it. This writes into the asking
agent's space, so nothing is copied without you: at notify and autonomous it asks
before every single fetch, and a propose agent copies nothing at all. Unlike other
destructive actions, this one can never be earned away.
$ asterism fetch writer researcher drafts/market-section.md
Fetching 'drafts/market-section.md' from researcher into writer's workspace.
Fetched 'drafts/market-section.md' from researcher into writer's workspace (55 B).
Only a file the other agent actually handed over can be fetched. A path it never produced is refused whatever is on disk — this brings across what you were shown, it is not a way to read another agent's files.
read-summary — read what it knows¶
This is the one mode where the other agent does no work at all. Nothing runs, no model is called, and it works with no model configured. It reads what that agent has already learned.
The two channels open so far do not authorize it. This is what "each mode is its own permission" looks like in practice — same two agents, already connected twice, still refused:
$ asterism summary writer researcher "pricing"
No active read-summary connection from writer to researcher. Open one first: asterism connect writer researcher --mode read-summary
$ asterism connect writer researcher --mode read-summary
Connected writer → researcher (read-summary). Use it with: asterism summary writer researcher ["<focus>"]
$ asterism summary writer researcher
researcher knows 3 of 3 ratified notes:
semantic Enterprise buyers weigh seat price over total contract value.
semantic The Q3 deck prices the team tier 12% above Q2.
convention Draft sections in Markdown, never HTML.
Only this extract crossed — not researcher's memory records, its runs, or anything it has not accepted.
Add a focus in quotes to ask about one subject:
$ asterism summary writer researcher "pricing"
Only what you have accepted can cross. A memory still waiting for your review, one you rejected, and anything archived all stay where they are — at any size of extract. What comes back is the knowledge itself, never the underlying records, when they were learned, which run produced them, or how sure the agent is.
Anything that looks like a password or key is removed before it crosses, and a note whose wording could be an attempt to steer the reading agent is held back whole. The extract says how many notes were held back and how many did not fit; ask again with a focus to reach those.
shared-brief — context both agents run with¶
Every other mode hands something back. This one carries something in.
$ asterism connect writer researcher --mode shared-brief
Connected writer → researcher (shared-brief). Use it with: asterism brief writer researcher "<brief>"
$ asterism brief writer researcher "Q3 launch: enterprise buyers, ship by Friday"
Briefed writer → researcher.
Both agents now run with it as standing context, until: asterism unbrief writer researcher
From then on both agents run with that brief in front of them — not just the one it was written to, and not only when they work together. It shapes their ordinary runs too, until you replace it, end it, or withdraw the channel. That is what makes it standing context rather than a longer way of writing a task.
Each agent sees the brief clearly marked as coming from the channel, not as its own purpose, so neither is fooled into treating another agent's words as its own. What you write is screened first: wording that reads as an attempt to steer or manipulate the other agent is refused outright — nothing is saved and nothing crosses.
An agent has one brief per channel; writing a new one replaces it. See what an agent is running with:
$ asterism briefs writer
Briefs for writer (1):
• → researcher · 1e572c21 (framing every run of both agents)
Q3 launch: enterprise buyers, ship by Friday
A brief frames BOTH agents' runs while it is live — the arrow shows whose channel carries it.
End the brief but keep the channel:
$ asterism unbrief writer researcher
Ended the brief on writer → researcher. Neither agent sees it from their next run.
The channel is still open — set a new brief with: asterism brief writer researcher "<brief>"
delegated-tool — borrow one tool, not the credential¶
The other four modes are about work the other agent does with its own head. This one is about a tool it holds — an address it can call using a credential of its own — and it is the only mode where the asking agent gets the use of something without ever getting the thing itself.
Two grants, not one, and the second is the point:
$ asterism connect writer researcher --mode delegated-tool
Connected writer → researcher (delegated-tool). Use it with: asterism delegate writer researcher <endpoint>
$ asterism delegate writer researcher issues
writer may now ask researcher to call 'issues' — and only that. researcher's credential stays with researcher.
Every call stops for you first: researcher asks before it sends anything, at any trust level.
Use it with: asterism call writer researcher issues
The channel says writer may ask for tool results at all; the second command says
which tool. So a tool you give researcher next month is not something writer can
reach through the channel you opened today — you name each one, and you can take one back
without disturbing the rest.
Asking is one command, and it stops for you every time:
$ asterism call writer researcher issues
writer is asking researcher to call 'issues' with researcher's credential.
Approve this destructive action? [y/N] y
What comes back is the tool's own answer — whatever that address returns, screened. The credential goes out with the call and comes back into nothing: not the answer you see, not either agent's record, not its memory.
That confirmation is not a setting you can turn off. A call that carries a credential
always asks, at every autonomy level, and it can never earn its way out of asking the way
other actions can — sending a credential somewhere is the one thing asterism will not
learn to do on its own. If the agent that owns the tool is at propose, nothing is sent
at all; it tells you what it would have done.
Changing the tool takes the grant back, because what was handed over is no longer what would be sent:
$ asterism api add researcher issues "https://api.github.com/repos/acme/site/pulls" --credential GITHUB_TOKEN
Bound api.issues for researcher — it may now send credential GITHUB_TOKEN to api.github.com.
No call happens without you: at notify and autonomous it pauses and asks; a propose agent only ever plans it.
This changed what the call sends, so writer can no longer ask researcher to make it.
Grant it again with: asterism delegate writer researcher issues
Seeing what is open¶
$ asterism connections writer
Connections for writer (5):
• → researcher · handoff · active · d0277553
• → researcher · artifact-only · active · 23487a14
• → researcher · read-summary · active · 1fcbb509
• → researcher · shared-brief · active · c3c463a4
• → researcher · delegated-tool · active · ba00a306
may call api.issues
→ outbound (this agent initiates over the channel) · ← inbound (the other agent initiates)
All five channels from the walkthrough, each still its own permission. → is outbound
(this agent initiates); ← is inbound (the other agent does). You only
ever see the named agent's own channels — it never reveals a channel between two other
agents.
Withdrawing a channel¶
$ asterism disconnect writer researcher --mode handoff
Disconnected writer → researcher (handoff). writer can no longer hand work to researcher.
Reconnecting opens a new channel — it does not bring the old one back.
What that takes away is more than the ability to ask for work:
- withdrawing an artifact-only channel means files already handed over can no longer be fetched — the list you were given stops resolving;
- withdrawing a read-summary channel stops it sharing what it knows, including anything learned while the channel was open;
- withdrawing a shared-brief channel un-frames the brief for both agents, from their next run;
- withdrawing a delegated-tool channel takes back every tool handed over on it at
once — which is why taking back a single tool has its own command,
undelegate.
Work already underway is not interrupted. If the other agent is paused waiting for you to confirm something, that confirmation still works and it still finishes in its own space — but nothing it produces afterwards comes back across the withdrawn channel.
Withdrawn channels stay listed, marked, after the open ones, so you can always see what was once open and that it is now closed:
$ asterism connections writer
Connections for writer (5):
• → researcher · artifact-only · active · 23487a14
• → researcher · read-summary · active · 1fcbb509
• → researcher · shared-brief · active · c3c463a4
• → researcher · delegated-tool · active · ba00a306
may call api.issues
• → researcher · handoff · revoked · d0277553 (withdrawn — nothing crosses it)
→ outbound (this agent initiates over the channel) · ← inbound (the other agent initiates)
Both agents' records keep showing the channel and the moment it was withdrawn. Every use of a channel is recorded on both agents' logs — that it happened, never the task text or the result:
asterism events tail writer
From the console¶
Everything here is also available over the install-wide console the dashboard runs on, so you can open channels, hand off work and read a summary from another machine. See the collaboration endpoints.
What "separate" means here¶
The separation these channels preserve is the same one described in what isolation means today: memory, secrets, skills, workspaces, autonomy and logs are scoped per agent and enforced on every read and write. A channel narrows what may cross that boundary to one named thing; it does not weaken the boundary.
That is logical scoping, not an OS-enforced jail. It is exactly as strong as the rest of the product's separation — no stronger because two agents are talking, and no weaker.
Where to go next¶
- Command reference → connect — every collaboration command, option by option.
- Concepts → Connections — the shorter statement of the same model.
- Dashboard — the console endpoints that expose all of this over HTTP, and the live terminal view over every agent.