by gebruder
The switchboard for the agent era. Per-channel isolation, encrypted credential vault, per-session hash-chained audit log. Single static Rust binary.
# Add to your Claude Code skills
git clone https://github.com/gebruder/wirkenLast scanned: 5/30/2026
{
"issues": [],
"status": "PASSED",
"scannedAt": "2026-05-30T16:06:04.318Z",
"npmAuditRan": true,
"pipAuditRan": true
}No comments yet. Be the first to share your thoughts!
30 days in the Featured rail
Wirken is the switchboard for the agent era. Message it on Telegram, Discord, Slack, Microsoft Teams, Matrix, WhatsApp, Signal, Google Chat, or iMessage, and the agent on the other end reads files, calls APIs, and runs tools on your behalf. Each channel gets its own line. Every call is logged before it connects.
Wirken ships as a single static Rust binary and works with Ollama, Anthropic, OpenAI, Gemini, Bedrock, Tinfoil, Privatemode, or any OpenAI-compatible endpoint. MIT licensed.
Each channel runs in its own adapter process with a distinct Ed25519 IPC identity and its own vault-scoped token set. Credentials sit in an XChaCha20-Poly1305 vault keyed from the OS keychain, with per-credential expiry and manual rotation tracked in the store. Every agent action, tool call, LLM request, and response is written to a per-session SHA-256 hash-chained audit log. The log forwards to Datadog, Splunk HEC, Microsoft Sentinel, or a webhook when SIEM is configured. A separate OpenTelemetry projection ships GenAI semantic-convention spans over OTLP/HTTP+JSON to any OTLP-compatible backend; Microsoft documents a direct OTLP contract for non-SDK Agent 365 integration, which this projection implements (see docs/integrations/agent365.md for the wire shape and the per-release verification gate). Permissions follow a three-tier model scoped per agent. Parent agents that spawn children declare per-child ceilings: tool allowlist, maximum permission tier, max rounds, max runtime.
Download the latest release binary:
curl -fsSL https://raw.githubusercontent.com/gebruder/wirken/main/install.sh | sh
wirken setup
wirken run
Pin the installer before piping. The committed install.sh has this SHA-256:
73e678196ea073608e902c8ab11a01ede07e0d37fddccaa20c43fa5d62bd52f5
Verify it yourself:
curl -fsSL https://raw.githubusercontent.com/gebruder/wirken/main/install.sh | sha256sum
The installer then fetches checksums.sha256 and checksums.sha256.sig from the release, verifies the signature with ssh-keygen -Y verify against a signing key embedded in the script, and verifies the binary's SHA-256 against the signed checksums. Every failure path is fail-closed: missing signature, missing checksum, mismatched digest, or a machine without sha256sum/shasum aborts install. The only override is WIRKEN_ALLOW_UNVERIFIED=1, which warns on stderr and is documented in docs/release-signing.md.
Prebuilt binaries are available for Linux (x86_64, aarch64), macOS (x86_64, Apple Silicon), and Windows 11 (x86_64). The Linux binaries are statically linked against musl with no glibc dependency. Windows users: the bash installer above does not apply; see docs/windows.md for the Windows install path and the feature-set differences (Signal adapter, orchestrator-push, service installer, and cron presets are Linux/macOS only).
wirken setup walks you through six steps:
wirken setup
────────────
Wirken is the switchboard between your messaging channels and an
AI agent you control. Credentials never reach the LLM. Every
action is logged in a signed, hash-chained audit log.
Setup walks through six steps: provider, channels, credentials,
service, sandbox, audit. About a minute.
Continue [Y/n]: y
... (six interactive steps) ...
Setup complete!
Provider: anthropic (claude-sonnet-4-6)
Channels: Telegram
Next steps:
wirken channel add <channel> Add another messaging channel
wirken credentials add <name> Add or rotate a key
wirken doctor Verify the install
wirken session list See active conversations
WebChat: http://localhost:18790
Start wirken: wirken run
wirken run starts wirken. It spawns adapter processes, accepts authenticated connections, routes messages to the agent, and serves a WebChat UI at http://localhost:18790:
wirken v1.8.1
──────
Provider: ollama/llama3.2
Ollama version: 0.19.0
Route: Telegram -> agent:default
WebChat: http://localhost:18790
Wirken running. Press Ctrl+C to stop.
All local services bind to 127.0.0.1. Wirken never instructs you to bind inference servers, WebChat, or any local endpoint to 0.0.0.0.
Install as a system service so wirken starts on login:
wirken setup --install-service
graph TD
Channels["Telegram · Discord · Slack · Teams · Matrix · WhatsApp · Signal · Google Chat · iMessage"]
Channels -- "UDS · Ed25519 · Cap'n Proto" --> Registry
subgraph Wirken
Registry[Adapter Registry] --> Router
Router --> Detect[Injection Detection]
Detect --> Factory[AgentFactory]
Factory --> Agent[Agent Runtime]
Agent --> Context[Context Engine]
Agent --> Permissions
Agent --> Skills
Agent --> Tools
Agent --> Vault --> Keychain
subgraph Execution
Tools --> Sandbox[Docker / gVisor / Wasm]
end
SessionLog["Session Log\n(per-session hash chain, attested)"]
end
Agent -- "UDS" --> McpProxy["MCP Proxy\n(separate process)"]
McpProxy -- "stdio · HTTP · OAuth2" --> McpServers[MCP Servers]
Agent -- HTTPS --> LLM[LLM Providers]
Agent -- "spawn_subagent" --> Factory
Detect -.-> SessionLog
Permissions -.-> SessionLog
Tools -.-> SessionLog
SessionLog -.-> SIEM[SIEM / Webhook]
Each channel adapter runs as a separate OS process. Adapters authenticate to the gateway with a per-adapter Ed25519 challenge-response handshake over a Unix domain socket. Messages are serialized with Cap'n Proto (zero-copy, traversal-limited). An adapter can only deliver inbound messages for its own channel and request outbound sends for its own channel. It cannot invoke tools, read other channels' sessions, or access other channels' credentials.
Channel isolation operates at two levels. The active mechanism is process-level: each channel runs in its own OS process with a distinct ed25519 identity. The IPC crate also defines a sealed Channel trait and SessionHandle<C: Channel> type that makes cross-channel handle conversions a compile error. This type-level API is not yet threaded through the production message path, where the channel discriminator is a string field on the Cap'n Proto inbound frame. If an adapter process is compromised, the blast radius is exactly one channel because the gateway's IPC boundary, running in a separate memory-safe process, prevents lateral movement.
The MCP proxy also runs out-of-process over a Unix domain socket, with the vault handle isolated in the proxy. MCP servers connect via stdio, HTTP, or OAuth2, and the agent process never sees MCP credentials.
Two distinct boundaries protect MCP credentials. Process isolation is per-MCP-server-config: every server entry in mcp.json spawns its own subprocess at the wirken UID, with its own stdin/stdout pipe and its own environment, and the agent process never holds plaintext bearer tokens or OAuth2 client secrets — those live behind the proxy's vault handle. Vault ACLs are per-credential-name: the credential store keys every entry by name (e.g. slack-token, github-pat), and a connector that asks for a credential it was not configured for receives a NotFound rather than a value from another connector's slot. The two are independent. A compromised MCP child cannot read another child's credentials because process isolation keeps every child to its own configured token set; a compromised credential name cannot be retrieved by an unrelated component because the vault store gates by name. Neither alone is sufficient, and the combination is what gives the MCP path its credential-scoping property.
Agents are stateless between turns. The AgentFactory wakes an agent for each inbound message by replaying its session log. Conversations are durably logged as typed session events (user messages, assistant messages, tool calls, tool results, LLM request/response metadata) in an append-only, per-session hash-chained table. If the agent crashes mid-turn, the harness detects incomplete tool rounds on wake and surfaces them as failures rather than silently re-executing side effects. A context engine trims conversations under each model's token budget before every LLM call, preferring to drop old tool results before touching user or assistant text.
Agents can delegate bounded subtasks to child agents via spawn_subagent. The operator configures a per-child capability ceiling (tool allowlist, max permission tier, max rounds, max runtime). Children run headless with no interactive approvals, isolated session logs, and a hard depth cap of 4.
wirken session verify replays the log offline and re-checks message hashes, deterministic tool results, and chain integrity. Tampered sessions break the chain.SessionHandle<Telegram> vs SessionHandle<Discord>) exists in the IPC crate and is r