feat(cli): close cross-agent loop — auto-handle agent.ask + ${COMMONLY_AGENT_TOKEN} substitution#237
Closed
feat(cli): close cross-agent loop — auto-handle agent.ask + ${COMMONLY_AGENT_TOKEN} substitution#237
Conversation
…Y_AGENT_TOKEN} substitution
Two follow-ups from the 2026-04-17 ADR-003 Phase 4 live validation,
both blocking a fully-automated cross-agent demo without manual curl
or post-attach token-patching.
Track A — agent.ask event handling in performRun
- New ASK_EVENT_TYPES + PASSIVE_ACK_EVENT_TYPES sets alongside the
existing CHAT_EVENT_TYPES.
- buildPromptForEvent renders agent.ask events into a structured
prompt (fromAgent, requestId, question + instruction to call
commonly_respond_to_ask). Chat events keep the verbatim payload
forwarding they had before.
- Asks suppress the pod-message post — responses go via MCP, not chat.
Outcome on the ack record is 'responded' for asks, 'posted' for chat.
- agent.ask.response events are passive-acked (v1): the asker drops
them. Resuming the original session with the answer is post-v1
work — needs requestId-keyed session state.
- Spawn ctx now carries runtimeToken + instanceUrl so adapters can
use them (Track B uses them to substitute placeholders).
Track B — ${COMMONLY_*} substitution in claude adapter
- writeMcpConfig walks every MCP server's env values, command args,
and url, substituting:
${COMMONLY_AGENT_TOKEN} → ctx.runtimeToken
${COMMONLY_API_URL} → ctx.instanceUrl
${COMMONLY_INSTANCE_URL} → ctx.instanceUrl (alias)
- One-pass literal substitution; works inside larger strings.
- Unknown ${COMMONLY_*} placeholders are left intact so typos surface
as runtime MCP errors, not silent empties.
- Falsy ctx values are a no-op (placeholder preserved) so users can
diagnose missing context without a confusing empty-string error.
Tests: 135/137 cli tests pass (4 new run-loop, 5 new claude env).
Closes the manual-curl gap from the cross-agent demo report.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
Author
|
Closing as I'm splitting this — Track A doesn't pass the design bar after a re-read, Track B is good and will land separately. Why Track A is being deferred (not merged): Auto-handling What's next here:
Branch + commit preserved on origin: |
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two follow-ups from the 2026-04-17 ADR-003 Phase 4 live validation report, both blocking a fully-automated cross-agent demo without manual curl or post-attach token-patching.
Track A —
agent.askevent handling inperformRunASK_EVENT_TYPES+PASSIVE_ACK_EVENT_TYPESsets alongside the existingCHAT_EVENT_TYPES.buildPromptForEventrendersagent.askevents into a structured prompt (fromAgent, requestId, question + instruction to callcommonly_respond_to_ask). Chat events keep verbatim payload forwarding.respondedfor asks,postedfor chat.agent.ask.responseevents are passive-acked (v1): asker drops them. Resuming the original session with the answer is post-v1 work — needs requestId-keyed session state.runtimeToken+instanceUrlso adapters can use them.Track B —
${COMMONLY_*}substitution in claude adapterwriteMcpConfigwalks every MCP server'senvvalues, command args, andurl, substituting:${COMMONLY_AGENT_TOKEN}→ctx.runtimeToken${COMMONLY_API_URL}→ctx.instanceUrl${COMMONLY_INSTANCE_URL}→ctx.instanceUrl(alias)${COMMONLY_*}placeholders are left intact so typos surface as runtime MCP errors, not silent empties.Live demonstration
Two claude agents (
asker,target) attached with a shared env file using${COMMONLY_AGENT_TOKEN}placeholders. User triggered the asker via chat mention. Result, with no manual intervention:Target's actual response from the
AgentAskrecord:Test plan
cd cli && npm test— 135/137 passing (4 new run-loop, 5 new claude env, 2 skipped Linux-only). Zero regressions.docs/REVIEW.mdcommonly-devend-to-end with placeholder env (no hardcoded tokens) — full bidirectional ask/respond flow with zero manual curlKnown follow-ups (deliberately out of scope)
agent.ask.responsearrives. Needs requestId-keyed session state. v1 ack-and-drops; asker's next turn picks up the answer from memory or a context call.🤖 Generated with Claude Code