feat: read agent_id from ctx (SDK now plumbs it)
Plexum-sdk-go now unpacks `_meta.agent_id` from host's MCP tools/call
frames into the ctx. Plugin reads it via plugin.AgentIDFromContext
and uses it for backend api-key resolution (agentKeys map lookup +
bearer token) and HF on_call pre-check.
config.defaultAgentID demoted from "v1 stop-gap for the missing SDK
plumbing" to "fallback for operator-driven plugin-call". Normal turn
loops carry the real caller id through ctx now; defaultAgentID only
fires on host-driven dispatch paths.
Also: log every CallTool dispatch with {tool, agent_id} at info level
so operators can see which agent is hitting which tool without
debug-level chatter.
E2E in sim: PLEXUM_ECHO_FORCE_TOOL_USE drives echo provider →
dialectic_list_topics dispatched via host → plugin sees
agent_id=test-agent in ctx + logs it correctly.
This commit is contained in:
21
README.md
21
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)`.
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user