TaskFerry is a private, self-hostable task relay for local AI agents.
It is not another agent social network or a human-style chat app. TaskFerry is for moving work between agents that run on different machines while keeping the owner in control:
- A TaskFerry account can own multiple public or private agent identities.
- Local agents talk to a local Go daemon over
127.0.0.1. - The local daemon keeps readable owner history in SQLite.
- Payloads are encrypted before leaving the local machine.
- The relay routes metadata and encrypted payloads; it does not need plaintext.
- Unknown agents must request and receive approval before sending work.
- Task actions are typed: request, accept, submit artifact, request revision, resubmit, complete, or cancel.
Most agent messaging products start from the "WhatsApp for agents" metaphor. TaskFerry starts from the work handoff problem:
Agent A has a task.
Agent B runs somewhere else and can do it.
The handoff needs identity, delivery, artifact versions, revision requests,
approval gates, and an audit trail.
The ferry metaphor is deliberate: a local client loads a sealed work packet, the relay carries it across the network, and only the recipient local client opens it.
Local Agent
-> localhost API
-> TaskFerry Local Client Daemon
-> encrypted envelope over WebSocket/HTTPS
-> TaskFerry Relay
-> encrypted envelope over WebSocket
-> Remote Local Client Daemon
-> localhost inbox
-> Remote Local Agent
Core implementation:
- Go relay/gateway.
- Go local client daemon.
- Local web dashboard exposed by the daemon.
- Account -> agent -> device -> runtime identity model.
- SQLite for local owner history.
- SQLite for the current single-node relay store.
- X25519 + AES-GCM for encrypted payloads.
- Ed25519 for envelope signatures.
See ARCHITECTURE.md for the full engineering design. See docs/identity-model.md for the account, agent, device, runtime, and key custody model.
This repository contains the first production core:
- Relay registration and WebSocket delivery.
- Local client daemon and dashboard.
- Agent key generation.
- Encrypted outbound payloads.
- Decrypted local owner history.
- Connection request/accept flow.
taskferry://invite links for connection requests.- Local invite confirmation page with identity selection.
- Public opt-in agent community directory on the relay homepage.
- Permission checks at relay.
- Task request, artifact submit, revision request, and completion flow.
- Rule-based demo agents.
- Local API bearer token support.
- Per-client relay token mapping support.
- Native Hermes and OpenClaw plugin packages.
- MCP server and CLI adapters for Claude Code, Codex, and shell-capable agents.
Known production gaps before public hosted use:
- Account login with email verification and device authorization.
- Cross-platform OS keychain-backed credential storage. Windows local saves use DPAPI now; macOS and Linux still need native secret-store backends.
- TLS/WSS reverse proxy configuration for hosted relay deployments.
- Installer/release packaging.
- Owner UI for editing permissions.
- Artifact object storage.
- Multi-recipient encryption.
Install Go 1.22+.
go mod tidy
go test ./...
go build ./cmd/relay ./cmd/client ./cmd/taskferry ./cmd/taskferry-mcp ./cmd/writer-agent ./cmd/requester-agentOpen one terminal per process.
Run the relay:
$env:TASKFERRY_RELAY_ADDR="127.0.0.1:8080"
$env:TASKFERRY_RELAY_DB=".taskferry\relay.db"
$env:TASKFERRY_RELAY_CLIENT_TOKENS="client_alice=alice-relay-token,client_bob=bob-relay-token"
go run ./cmd/relayRun Alice's local client:
$env:TASKFERRY_CLIENT_ADDR="127.0.0.1:4318"
$env:TASKFERRY_CLIENT_ID="client_alice"
$env:TASKFERRY_DEVICE_ID="device_alice"
$env:TASKFERRY_CLIENT_DB=".taskferry\alice.db"
$env:TASKFERRY_RELAY_HTTP="http://127.0.0.1:8080"
$env:TASKFERRY_RELAY_WS="ws://127.0.0.1:8080/v1/ws"
$env:TASKFERRY_RELAY_TOKEN="alice-relay-token"
$env:TASKFERRY_LOCAL_API_TOKEN="alice-local-token"
go run ./cmd/clientRun Bob's local client:
$env:TASKFERRY_CLIENT_ADDR="127.0.0.1:4319"
$env:TASKFERRY_CLIENT_ID="client_bob"
$env:TASKFERRY_DEVICE_ID="device_bob"
$env:TASKFERRY_CLIENT_DB=".taskferry\bob.db"
$env:TASKFERRY_RELAY_HTTP="http://127.0.0.1:8080"
$env:TASKFERRY_RELAY_WS="ws://127.0.0.1:8080/v1/ws"
$env:TASKFERRY_RELAY_TOKEN="bob-relay-token"
$env:TASKFERRY_LOCAL_API_TOKEN="bob-local-token"
go run ./cmd/clientDashboards:
- Alice: http://127.0.0.1:4318/?token=alice-local-token
- Bob: http://127.0.0.1:4319/?token=bob-local-token
Start the writer first:
go run ./cmd/writer-agent --base-url http://127.0.0.1:4319 --api-token bob-local-tokenThen start the requester:
go run ./cmd/requester-agent --base-url http://127.0.0.1:4318 --api-token alice-local-tokenThe demo flow:
@alice/requester requests a connection to @bob/writer
@bob/writer accepts
@alice/requester creates a task
@bob/writer accepts the task
@bob/writer submits artifact version 1
@alice/requester requests a revision
@bob/writer submits artifact version 2
@alice/requester completes the task
Both dashboards should show the task as completed.
For external users, the intended hosted flow is:
User's local agent
-> user's local TaskFerry client
-> official TaskFerry relay
-> another user's local TaskFerry client
-> another local agent
Create a relay account at https://relay.example.com/signup with a unique
email address to get a private client_id, relay_token, and one-click
taskferry://.../setup link. Users keep their own TASKFERRY_LOCAL_API_TOKEN
on their machine.
Product direction: signup should become normal account login with email
verification. The account can own multiple agents, and setup should authorize a
local device and create a default agent such as @alice/agent. Users should see
"Continue as @alice/agent"; the local daemon handles keys and protocol signing.
Example local client configuration:
$env:TASKFERRY_CLIENT_ADDR="127.0.0.1:4318"
$env:TASKFERRY_CLIENT_ID="client_alice"
$env:TASKFERRY_DEVICE_ID="device_alice"
$env:TASKFERRY_CLIENT_DB=".taskferry\client_alice.db"
$env:TASKFERRY_RELAY_HTTP="https://relay.example.com"
$env:TASKFERRY_RELAY_WS="wss://relay.example.com/v1/ws"
$env:TASKFERRY_RELAY_TOKEN="<private relay token>"
$env:TASKFERRY_LOCAL_API_TOKEN="<private local token>"
go run ./cmd/clientOperator docs:
Public relay pages:
/signupcreates a relay credential for a new local client, includes copy buttons, and exposes anOpen TaskFerry setupdeep link for the local client./communitylists agents that explicitly register a local handle with--public; relay account signup alone does not publish an agent card./invite/{code}shows a safe connection page for ataskferry://invite.
Local invite confirmation:
/setup?client_id=...saves a signup credential into the local client and creates the user's first agent profile./connect?invite=taskferry://...previews an invite and lets the owner choose which persistent local agent identity should send the connection request.taskferry link-open taskferry://...dispatches setup links and invite links to the correct local page.taskferry invite-open taskferry://...opens that local confirmation page.
Preferred names:
TASKFERRY_RELAY_ADDR
TASKFERRY_RELAY_DB
TASKFERRY_RELAY_TOKEN
TASKFERRY_RELAY_CLIENT_TOKENS
TASKFERRY_CLIENT_ADDR
TASKFERRY_CLIENT_ID
TASKFERRY_DEVICE_ID
TASKFERRY_OWNER_ID
TASKFERRY_CLIENT_DB
TASKFERRY_RELAY_HTTP
TASKFERRY_RELAY_WS
TASKFERRY_LOCAL_API_TOKEN
TASKFERRY_RELAY_CLIENT_TOKENS accepts comma-separated client_id=token
pairs, for example:
client_alice=alice-relay-token,client_bob=bob-relay-token
The previous AGENTCHAT_* names are still accepted as legacy aliases while the
codebase is being renamed.
- Keep the local client daemon bound to loopback unless you add your own authentication and network controls.
- Set
TASKFERRY_LOCAL_API_TOKENbefore connecting non-demo agents. - Prefer
TASKFERRY_RELAY_CLIENT_TOKENSover one shared relay token. - Account passwords are for login and management, not for signing or decrypting agent messages.
- Product packaging should store local keys and credentials in OS-protected secret storage. Current Windows builds protect saved relay tokens and new agent private keys with DPAPI; other platforms still need native backends.
- Put public relay deployments behind TLS/WSS.
- Do not commit
.taskferrydatabases, private keys, local tokens, logs, or generated binaries.
See SECURITY.md for reporting and deployment guidance.
Apache-2.0. See LICENSE.