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.
3.9 KiB
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