This guide covers EvoDuck's WebSocket plugin system. It is not MCP.
If you only need to add external tools for agents, prefer MCP first. Use plugins when you need provider, channel, or hook-level extensions.
The plugin system currently supports four capability types:
toolproviderchannelhook
tool: exposes external functionality as agent-callable toolsprovider: adds model provider integrationschannel: adds message bridgeshook: observes or influences runtime events
plugins:
ws_server:
host: 127.0.0.1
port: 19000
plugins:
echo-tool:
enabled: true
type: local
command: ["go", "run", "./plugins/echo-tool"]
restart: never
capabilities:
allow: ["tool"]enabledtypecommandenvironmenturltokenrestartrestart_delaymax_restartsoverridecapabilities.allowconnect_timeoutrequest_timeout
Validation checks:
typemust belocalorremotelocalrequirescommandremoterequiresurlcapabilities.allowmay only containtool,provider,channel, orhook
Local plugins are usually started by EvoDuck. You do not need to start them manually.
EvoDuck injects environment variables such as:
EVODUCK_PLUGIN_IDEVODUCK_PLUGIN_TOKENEVODUCK_WS_URL
The plugin then connects over WebSocket and registers its capabilities.
Current behavior:
toolcapabilities are wrapped as tool adapters and registered into the agent tool table.providercapabilities are registered into the LLM registry.channelcapabilities create channel bridges.hookcapabilities participate in runtime hook dispatch.
Repository demos:
plugins/echo-toolplugins/mock-providerplugins/mock-channelplugins/mock-hook
Recommended reading order:
plugins/echo-tool/README.mdplugins/mock-provider/README.mdplugins/mock-channel/README.mdplugins/mock-hook/README.md
A tool plugin should:
- Read
EVODUCK_PLUGIN_ID,EVODUCK_PLUGIN_TOKEN, andEVODUCK_WS_URL. - Connect to the plugin WebSocket server.
- Send a
registerrequest with atoolcapability. - Handle
tool.executerequests. - Return a response frame with the tool result.
Hooks can be observer hooks or mutating hooks.
Examples:
after_tool_callafter_llm_completebefore_tool_callbefore_llm_callbefore_agent_startbefore_message_sendafter_message_receiveon_conversation_binding
Mutating hooks can block or patch selected runtime behavior.
- Keep plugin request timeouts short and explicit.
- Use
restart: neverfor development fixtures. - Use capability allowlists to limit plugin scope.
- Prefer synthetic test data in demo plugins.