diff --git a/README.md b/README.md index c0df93d..bf2e247 100644 --- a/README.md +++ b/README.md @@ -59,18 +59,20 @@ Restart the host afterwards: `systemctl --user restart plexum`. | `agentKeys` | `{}` | Per-agent bearer token overrides. | | `defaultAgentID` | — | Agent id reported to the backend when host hasn't surfaced one via tool ctx. | -## How agent identity is resolved (v1 limitation) +## How agent identity is resolved `Dialectic.OpenclawPlugin` got the calling agent's id via the OpenClaw -framework's `ctx.agentId`. The Plexum SDK doesn't yet surface this on -tool dispatch — same constraint `HarborForge.PlexumPlugin` hits. v1 -falls back to `config.defaultAgentID`. Multi-agent claws can configure -`agentKeys` but the bearer token used per call is selected against the -config default (not the true caller), which is fine for a homogeneous- -role claw but won't sort signed verdicts apart by agent. +framework's `ctx.agentId`. The Plexum SDK now propagates the same +information: the host attaches `_meta.agent_id` to every MCP +`tools/call` frame it dispatches on an agent's behalf, and SDK +serve.go unpacks it into the ctx. Plugins read it via +`plugin.AgentIDFromContext(ctx)`. -The fix (deferred): plumb `AgentContext` through `ToolPlugin.CallTool` -in `Plexum-sdk-go`. Once landed, swap `AgentIDFromCtx` to read it. +`config.defaultAgentID` remains as a fallback used only on host paths +that genuinely carry no agent context — operator-driven +`plexum plugin-call` invocations for debugging, etc. Leave it empty +in a normal deployment; tool calls coming from real turn loops will +always carry the caller agent id. ## HF on_call coverage pre-check @@ -86,7 +88,6 @@ to make the skip explicit (matches the OpenClaw plugin escape hatch). ## Deferred items -- **Per-call agent id** — see "How agent identity is resolved" above. - **HF window-coverage check** — needs a backend-side endpoint or a Plexum cross-plugin contract for `harbor-forge` to surface `HasOnCallCovering(agentID, from, to)`. diff --git a/cmd/plexum-dialectic-plugin/main.go b/cmd/plexum-dialectic-plugin/main.go index dbedb73..471039e 100644 --- a/cmd/plexum-dialectic-plugin/main.go +++ b/cmd/plexum-dialectic-plugin/main.go @@ -56,9 +56,14 @@ func (p *dialecticPlugin) Init(ctx context.Context, host sdkplugin.HostAPI) erro Config: p.cfg, Host: host, AgentIDFromCtx: func(ctx context.Context) string { - // v1: SDK doesn't surface the calling agent on tool ctx. - // Fall back to the per-claw default. Multi-agent claws will - // need SDK ctx plumbing — tracked upstream. + // Host attaches the caller agent id via tools/call + // `_meta.agent_id`; SDK unpacks it into ctx. + if id := sdkplugin.AgentIDFromContext(ctx); id != "" { + return id + } + // Fallback for host paths that don't carry an agent + // (CLI plugin-call against this plugin from an operator + // debugging the deployment). Empty when not set. return p.cfg.DefaultAgentID }, } @@ -66,6 +71,10 @@ func (p *dialecticPlugin) Init(ctx context.Context, host sdkplugin.HostAPI) erro } func (p *dialecticPlugin) CallTool(ctx context.Context, name string, input json.RawMessage) (sdkplugin.ToolResult, error) { + p.host.Log("info", "tools/call dispatched", map[string]any{ + "tool": name, + "agent_id": sdkplugin.AgentIDFromContext(ctx), + }) return tools.Dispatch(ctx, p.deps, name, input) }