feat: agent-to-agent platform on ZeroClaw 0.8.2 — rooms, delegation, A2A ingress
Builds on the v0.8.2 runtime. Four workstreams, all behind the §15 MCP door:
- Group rooms (Phase 1): migration 0026; N-way threads repo with a DM/room
count-guard; chat.send {room} + room.create/invite/leave tools; RoomMessage
-> room.message SSE; /api/claw-chat/rooms* APIs; Observer room badge.
- Per-claw door identity: door caller_agent resolves the X-ZeroClaw-Agent
header (set by the fork) to the specific claw, falling back to roster[0].
- Gated delegation bridge (Phase 3): clawmates__delegate door tool drives a
sibling via the existing /ws/chat ZeroClawDriveExecutor (not A2A); self-deny,
per-workspace hourly budget, audit trail, untrusted-banner result. Native
in-daemon delegation stays off (it would bypass the door).
- A2A tenant ingress (Phase 2): migration 0027 (workspace_a2a + a2a_tokens);
runtime_provision enable_a2a_server/publish_claw; routes/a2a.rs tenant-aware
proxy (per-workspace tokens, injected internal bearer, daemon stays internal,
cards URL-rewritten to the cm-api edge); a2a.invoked taxonomy.
Tests: cm-db room repos, cm-runtime chat tools, door units. sqlx cache updated.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
1a531e91cd
commit
cbfa0ff24f
@@ -198,6 +198,32 @@ impl ZeroClawDriveExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
/// Drive agent `alias` as a delegated sub-task and return its result. Reuses
|
||||
/// the same gateway drive as topology turns + the governor, so a delegated
|
||||
/// turn carries the same blocked-action / token instrumentation in its
|
||||
/// [`TurnOutcome`]. The target is tool-free behind the MCP door, so a
|
||||
/// delegated turn adds no new egress (§15 holds — the bridge only causes an
|
||||
/// in-workspace agent to run a turn; anything it does is independently gated
|
||||
/// at the door).
|
||||
pub async fn delegate(
|
||||
&self,
|
||||
alias: &str,
|
||||
task: &str,
|
||||
context: &[String],
|
||||
) -> Result<TurnOutcome, OrchestratorError> {
|
||||
let mut prompt = format!(
|
||||
"You are being delegated a sub-task by another agent on your team. \
|
||||
Do it concisely and return only your result.\n\nTask: {task}"
|
||||
);
|
||||
if !context.is_empty() {
|
||||
prompt.push_str("\n\nContext from the delegating agent:\n");
|
||||
for (i, c) in context.iter().enumerate() {
|
||||
prompt.push_str(&format!("[{i}] {c}\n"));
|
||||
}
|
||||
}
|
||||
self.drive(alias, &prompt).await
|
||||
}
|
||||
|
||||
/// Read frames until a terminal (`done`/`error`/`approval_request`) event.
|
||||
async fn drain<S>(ws: &mut S) -> Result<TurnOutcome, OrchestratorError>
|
||||
where
|
||||
|
||||
Reference in New Issue
Block a user