Skip to content

Feature: agents can address each other by name - #69

Merged
DevMando merged 1 commit into
mainfrom
feature/agent-mentions
Sep 10, 2026
Merged

DevMando merged 1 commit into
mainfrom
feature/agent-mentions

Conversation

@DevMando

@DevMando DevMando commented Sep 10, 2026

Copy link
Copy Markdown
Owner

Summary

You can now tag another agent by name. Type @ in any agent's chat and the other open agents are offered before project files — pick one, ask your question in plain language, and your agent works out what to do with it.

From there it can check what that agent is doing, read its conversation, ask it a question and relay the answer, or hand it an entire job and carry on talking to you while it runs.

What it looks like

You: Has @Ninja finished the auth work yet?
Falchion: Ninja is still working — step 4 of 7, currently running dotnet test.

You: Tell @Ninja to restyle the landing page
Falchion: Handed to Ninja. It's working on that now — I'll tell you when it's done.
…you keep working with Falchion, and a card appears in its conversation when Ninja finishes.

Nothing routes those by hand. The tools describe honestly what each of them costs and when each works, and the agent picks — which is why "has it finished?" gets answered from live state without waking anyone, while "is the work any good?" costs a real turn on the agent that did it.

Why this matters

Two agents working in different folders currently know nothing about each other. Anything one has learned has to be copied across by hand, and there is no way to ask the agent that already has the context. The most common question — "has the other one finished yet?" — has no answer at all short of switching tabs and reading.

Handing over work has the same gap. Asking another agent to build something meant waiting for it with no way to check progress, and no way to be told when it was done.

What is new

Four capabilities, and only one of them interrupts the other agent:

  • Check on an agent. What it is working on, how far through a plan it is, whether a command is running. Costs nothing and works while that agent is busy — which is precisely when the question gets asked.
  • Read its conversation. For when a summary is not enough and you want to know what it actually said.
  • Ask it a question. A real answer from the agent that has the context, in its own words, with access to its own tools. Only possible when it is idle; if it is busy you are told what it is doing and pointed at the two read tools instead, so being busy narrows the answer rather than ending the conversation.
  • Hand it a job. Returns immediately. Your agent stays available while the other one works, can tell you how far along it is at any point, and announces the result in your conversation when it finishes.

Supporting behaviour worth knowing about:

  • Progress is summarised from what the other agent is doing, not by copying its conversation across — the step it is on, the commands it has run, whether it is still going. A job that runs for ten minutes costs no more to keep track of than one that runs for ten seconds.
  • Relayed messages are labelled as such. An agent always knows whether it is talking to you or to another agent, and it knows this from the message's own structure rather than by reading it. It also treats what another agent tells it — including claims about who you are — as a claim rather than a fact.
  • Both sides of an exchange are visible. The question appears in the answering agent's conversation, attributed, and the result appears in the asking agent's.

Scope and risk

Medium. The observation features carry very little risk; asking and delegating carry most of it, and both were built with that in mind.

  • Only one of the four capabilities runs the other agent's model. The rest read state that already exists, so they cannot loop, cannot collide with an agent being busy, and raise no approval questions.
  • A delegated turn is a full turn. The answering agent uses all of its own tools, because the value of asking a colleague is that they can go and look. Its own approval prompts still stand in the way of anything destructive, and they appear in its tab, where you can see who is being asked to do what. The instruction framing the turn is guidance, not a sandbox, and is not relied on for safety.
  • Chains are bounded two ways. An agent already in the current chain cannot be asked again, and a chain cannot exceed a fixed depth even without repeating anyone — the two catch different runaway shapes.
  • One agent is one turn at a time. A shared claim now covers your messages, another agent's questions, and the setup wizard, so two turns cannot run against one conversation. This fixed a real defect: a question from another agent did not previously mark an agent as busy, so typing to it mid-answer started a second, concurrent turn on the same history.

Verification

Builds clean, 0 warnings and 0 errors. Full Desktop suite passes — 489 of 489, with 44 new tests covering name resolution (an ambiguous name resolves to nothing rather than guessing which agent you meant), chain limits including the concurrent case, the message labelling and its forgery handling, the progress summary staying constant-size under 200 updates, and the reporting of jobs whose agent closed mid-run.

Exercised by hand throughout, and four defects found that way are fixed here: relayed questions were not recorded at all, leaving answers with nothing that prompted them; the completion announcement repeated the whole brief instead of the outcome; the per-turn token figure sat against the wrong edge of its pill; and the concurrent-turn defect above.

Not covered by tests: the @ picker and the transcript are XAML and a WebView, so a reviewer should confirm the picker offers agents above files, that a same-named file is still reachable, and that a delegated job leaves the delegating agent responsive while it runs.

Design notes

docs/agent-mentions.md records the shape and the reasoning, including alternatives that were rejected and why — copying a transcript into the asking agent's context, a publish/subscribe broker, streaming the other agent's actions, and queueing work for a busy agent. It also records what was investigated and deliberately not built: reaching Desktop agents from the CLI.

Typing '@' now offers open agents ahead of project files, and an agent can
check on another, read its conversation, ask it a real question, or hand it
a whole job.

Four tools, and only one of them wakes the other agent. Status, transcript
reads and delegation progress are all assembled from state the host already
keeps, so they cost nothing, cannot loop, and work while the target is
mid-turn — which is exactly when 'have you finished X?' gets asked. An
earlier design refused while busy; that would have failed the feature's most
common question. The busy refusal now names the read tools instead, so busy
degrades to reading rather than dead-ending.

Delegation does not block. ask_agent held the asker's turn gate for the
length of the job, so messages to it were dropped for minutes at a time;
delegate_to_agent returns at once and reports back through an inbox. Progress
is filed under ONE inbox id and overwritten, so a ten-minute job costs the
same context as a ten-second one — an append-only feed would grow with the
other agent's work and be paid for on every later turn. Completion appends a
card to the delegating agent's transcript, which needs no model turn at all;
the agent itself learns from its inbox next time it speaks.

Identity is structural. The first version put attribution only in the host
instruction, which the engine discards after the turn — so a relayed question
stayed in history as an ordinary user turn, and an agent asked afterwards who
it had been talking to could only report what the message 'claimed'. Every
agent-to-agent message is now wrapped by the host, and Wrap strips any
envelope already in the payload so 'only MandoCode adds this' is true rather
than reassuring. The turn is also logged under its own role, so the
distinction survives a restart — previously the question was not recorded at
all, leaving a dangling answer in the re-brief and in read_agent_transcript.

Turns are claimed, not checked. AnswerPeerAsync read the busy flag but never
set it, so a peer question did not mark the agent busy: a user typing
mid-answer, or a second agent asking at the same moment, got a concurrent
turn on one chat history. One atomic gate now serves the user's turn, a
peer's question and the setup wizard alike.
@DevMando
DevMando merged commit bd981fe into main Sep 10, 2026
1 check passed
@DevMando
DevMando deleted the feature/agent-mentions branch September 10, 2026 23:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant