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.
Dialectic.PlexumPlugin
Plexum plugin that gives agents tools to participate in Dialectic v2
debates. Ports Dialectic.OpenclawPlugin to the Plexum SDK.
Eight tools, one per Dialectic backend endpoint:
| Tool | Backend call | Notes |
|---|---|---|
dialectic_list_topics |
GET /api/topics |
filters: status/visibility/limit/offset |
dialectic_topic_detail |
GET /api/topics/{id} |
lifecycle + camps + verdict pointer |
dialectic_list_arguments |
GET /api/topics/{id}/arguments |
full transcript |
dialectic_propose_topic |
POST /api/topics |
4 lifecycle timestamps + verdict schema |
dialectic_signup |
POST /api/topics/{id}/signups |
with HF on_call coverage pre-check |
dialectic_post_argument |
POST /api/topics/{id}/arguments |
during debating only |
dialectic_submit_verdict |
POST /api/topics/{id}/verdict |
judge submits structured verdict |
dialectic_view_verdict |
GET /api/topics/{id}/verdict |
404 until judge submits |
Install
make install
Then add "dialectic" to ~/.plexum/plexum.json .plugins.allow and
write ~/.plexum/plugins/dialectic/config.json:
{
"backendUrl": "https://dialectic-api.hangman-lab.top",
"apiKey": "g1_xxx",
"defaultAgentID": "agent-xyz"
}
Multi-agent claws can use agentKeys instead of (or in addition to)
apiKey:
{
"backendUrl": "https://dialectic-api.hangman-lab.top",
"agentKeys": {
"agent-a": "g1_aaa",
"agent-b": "g1_bbb"
},
"apiKey": "g1_default_fallback",
"defaultAgentID": "agent-a"
}
Restart the host afterwards: systemctl --user restart plexum.
Config
| Field | Default | Purpose |
|---|---|---|
backendUrl |
https://dialectic-api.hangman-lab.top |
Dialectic API base. Env override: DIALECTIC_BACKEND_URL. |
apiKey |
— | Default bearer token. |
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
Dialectic.OpenclawPlugin got the calling agent's id via the OpenClaw
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).
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
dialectic_signup is supposed to verify the agent has an HarborForge
on_call slot covering the debate window before submitting. Like the
OpenClaw plugin's v1, this Plexum port currently degrades to
source="skipped" (HarborForge.Backend exposes no window-coverage
query yet). Signups go through with pre_validated=false so the
backend records the gap honestly.
Override with DIALECTIC_PLUGIN_BYPASS_HF=1 in the host's environment
to make the skip explicit (matches the OpenClaw plugin escape hatch).
Deferred items
- HF window-coverage check — needs a backend-side endpoint or a
Plexum cross-plugin contract for
harbor-forgeto surfaceHasOnCallCovering(agentID, from, to). - SSE subscriptions — agents poll via
dialectic_topic_detailto see status/argument changes. Once Dialectic.Backend ships SSE, adddialectic_subscribe. - Token-cost reporting —
dialectic_submit_verdictalready acceptstokens_input/tokens_output; wire automatic accounting once Plexum exposes per-turn usage telemetry through HostAPI.
See also
- Top-level design:
arch/DIALECTIC-V2-DESIGN.md - Backend:
Dialectic.Backend(Go) - OpenClaw port:
Dialectic.OpenclawPlugin