Summary
We want coding-agent completions to return to the same OpenClaw session/workspace that launched them when a callback target exists, with fallback to the current async/background event flow otherwise.
The cleanest place to originate that callback metadata is agentctl, because it is the cross-adapter supervision layer. Harness-specific completion events (Claude Code / OpenCode / Codex / etc.) should not each invent their own callback contract.
Why this belongs in agentctl
agentctl already has the right abstraction boundary:
- it is the normalized launch surface across adapters
AgentSession already has meta: Record<string, unknown>
- daemon launch metadata is already persisted and merged back into discovered sessions
- event consumers (OrgLoop, etc.) can read one consistent session schema instead of adapter-specific payloads
Problem to solve
Today, downstream systems can observe that a coding agent completed, but they don't know where to route the result back in OpenClaw. That means completion often wakes a separate background session instead of returning to the session that launched the work.
We want agentctl to carry an optional callback target so downstream systems can do:
- preferred: direct callback into the originating OpenClaw session
- fallback: existing webhook/new-session behavior
Proposed change
Add launch-time callback metadata support, stored in AgentSession.meta and surfaced everywhere session metadata already flows.
CLI surface
Add generic flags such as:
--callback-session <sessionKey>
--callback-agent <agentId> (optional / future-proof)
- possibly
--callback-workspace <workspace> if needed, though this may be redundant if session key is sufficient
This should work for single-adapter and multi-adapter launches.
Data model
Persist into session.meta, e.g.:
{
"openclaw_callback_session_key": "agent:personal:main",
"openclaw_callback_agent_id": "personal",
"launched_via": "openclaw"
}
Exact key names are up for discussion, but they should be:
- explicit
- stable
- not adapter-specific
Existing relevant evidence
A few notes from the current codebase:
AgentSession.meta already exists in src/core/types.ts
- daemon/session tracking already preserves
meta
sessionToJson() includes meta
- but
agentctl events currently streams only the Claude Code adapter's event stream (getAdapter("claude-code")), which is not sufficient as the universal event surface for this use case
That last point is important: this issue is about callback metadata, but it also underscores that the event surface should be thought of as agentctl-level, not Claude-specific.
Acceptance criteria
Notes
This issue does not require implementing delivery into OpenClaw sessions; that's downstream. The responsibility here is to make callback intent a first-class, cross-adapter part of agentctl's session metadata contract.
Summary
We want coding-agent completions to return to the same OpenClaw session/workspace that launched them when a callback target exists, with fallback to the current async/background event flow otherwise.
The cleanest place to originate that callback metadata is agentctl, because it is the cross-adapter supervision layer. Harness-specific completion events (Claude Code / OpenCode / Codex / etc.) should not each invent their own callback contract.
Why this belongs in agentctl
agentctlalready has the right abstraction boundary:AgentSessionalready hasmeta: Record<string, unknown>Problem to solve
Today, downstream systems can observe that a coding agent completed, but they don't know where to route the result back in OpenClaw. That means completion often wakes a separate background session instead of returning to the session that launched the work.
We want
agentctlto carry an optional callback target so downstream systems can do:Proposed change
Add launch-time callback metadata support, stored in
AgentSession.metaand surfaced everywhere session metadata already flows.CLI surface
Add generic flags such as:
--callback-session <sessionKey>--callback-agent <agentId>(optional / future-proof)--callback-workspace <workspace>if needed, though this may be redundant if session key is sufficientThis should work for single-adapter and multi-adapter launches.
Data model
Persist into
session.meta, e.g.:{ "openclaw_callback_session_key": "agent:personal:main", "openclaw_callback_agent_id": "personal", "launched_via": "openclaw" }Exact key names are up for discussion, but they should be:
Existing relevant evidence
A few notes from the current codebase:
AgentSession.metaalready exists insrc/core/types.tsmetasessionToJson()includesmetaagentctl eventscurrently streams only the Claude Code adapter's event stream (getAdapter("claude-code")), which is not sufficient as the universal event surface for this use caseThat last point is important: this issue is about callback metadata, but it also underscores that the event surface should be thought of as agentctl-level, not Claude-specific.
Acceptance criteria
agentctl launchaccepts callback metadata flagslist --json,status, and any event JSON output include the metadataNotes
This issue does not require implementing delivery into OpenClaw sessions; that's downstream. The responsibility here is to make callback intent a first-class, cross-adapter part of agentctl's session metadata contract.