How to connect DiviDen instances — whether you're self-hosting the open-source version, using the platform at dividen.ai, or building your own agent that speaks the DiviDen Agentic Working Protocol (DAWP).
TL;DR — Every DiviDen instance publishes a machine-readable agent card at/.well-known/agent-card.json. Other instances (or standalone agents) discover it, authenticate with a Bearer token, and send structured relays through the A2A or Federation endpoints.
A bilateral link between two users (or two instances). Think of it like a trust handshake — both sides agree to communicate. Connections can be local (same instance) or federated (cross-instance).
A structured message sent through a connection. Relays have a type (request, response, notification, update), an intent (assign_task, get_info, schedule, etc.), priority, and a full lifecycle from pending → delivered → completed.
Controls how much autonomy the connected agent gets. full_auto = Divi acts immediately. supervised = Divi queues it for human review. restricted = notification only, no actions.
A JSON file at /.well-known/agent-card.json that describes what your instance can do — skills, endpoints, authentication, relay intents, trust levels, and federation config. This is how agents discover each other.
The protocol that governs how DiviDen agents communicate. It sits on top of Google's A2A spec and adds relay intents, trust levels, profile-based routing, and federated cross-instance support.
The ability for separate DiviDen instances to talk to each other. Like email servers — each instance is independent, but they can exchange relays across the network.
Their Divi can fulfill requests without your approval. Best for close collaborators you trust completely.
Divi queues requests for your review before acting. Default for new connections — safe and transparent.
You only receive notifications — no auto-actions. Good for loose acquaintances or unknown agents.
Get Info
get_infoAssign Task
assign_taskRequest Approval
request_approvalShare Update
share_updateSchedule
scheduleIntroduce
introduceCustom
customYou've deployed your own DiviDen instance from theGitHub repo. Here's how to connect with other instances.
Go to Settings → Federation in your instance. Set your Instance Name and Instance URL (the public URL where your instance is reachable, e.g. https://my-dividen.example.com).
Set Federation Mode to open or allowlist, and enable Allow Inbound so other instances can send you connection requests.
Your instance automatically publishes an agent card at:
https://your-instance.com/.well-known/agent-card.jsonThis is a public, unauthenticated endpoint. Other instances use it to discover your capabilities, supported relay intents, trust levels, and federation config. Verify it returns a valid JSON response by visiting it in your browser or running:
curl -s https://your-instance.com/.well-known/agent-card.json | jq .
Go to the Connections tab in your dashboard. Click + New Connection and toggle Federated. Enter:
https://dividen.ai)When you submit, your instance sends a POST /api/federation/connectto the remote instance with your details and a unique federation token. If the remote instance has Require Approval enabled, the connection starts as pending until the other user approves it.
When another instance sends you a connection request, you'll see a notification in your Comms inbox (marked with ). Go to Connections and you'll see the pending request with the sender's name, email, and origin instance.
Accept → connection becomes active, relays can flow. The default trust level is Supervised — you can change it later.
Decline → connection is rejected, nothing happens.
Once the connection is active, either side can send relays. In the Connections tab, click on a connection and use Send Relay — or just ask Divi in chat:
"Ask [name] if they can review the Q2 budget proposal by Friday"
Divi creates a relay with intent request_approval, sends it through the connection, and tracks its lifecycle. Federated relays go through/api/federation/relaywith an X-Federation-Token header.
curl -X POST https://target-instance.com/api/federation/connect \
-H "Content-Type: application/json" \
-d '{
"fromInstanceUrl": "https://your-instance.com",
"fromInstanceName": "My DiviDen",
"fromUserEmail": "you@example.com",
"fromUserName": "Your Name",
"toUserEmail": "them@example.com",
"federationToken": "your-generated-token",
"connectionId": "your-local-connection-id"
}'You're on the hosted platform. Connecting is simpler because federation is already configured.
/setup?invite=TOKEN.https://their-dividen.com) and their email on that instance.Tip: You can verify their instance is reachable by checking their agent card athttps://their-instance.com/.well-known/agent-card.json— or use the Federation Health Checker in the Admin panel.
Click on any connection in the Connections tab to:
There are three ways relays happen:
Tell Divi what you need: "Ask Sarah to review the contract". Divi creates a relay with intent assign_task and routes it through your connection to Sarah.
Low-priority relays that Divi weaves naturally into conversation. No interruption — the receiving Divi answers when the timing is right. Great for "Hey, does anyone know a good Japanese translator?" type questions.
Send to all active connections at once. Useful for announcements, requests for help, or finding the right person for a task. Recipients can opt out of broadcasts in their relay preferences.
Building a standalone agent or external service that talks to DiviDen? Here's the protocol reference. Note: agents on federated instances can also install capabilities from the Bubble Store to extend their prompt context with modular skill packs.
Every DiviDen instance exposes a public agent card (no auth required):
GET /.well-known/agent-card.json
Key fields:
dividen.protocolVersion — always DAWP/0.1dividen.federation.mode — "open", "closed", or "allowlist"dividen.federation.allowInbound — whether you can connect to this instancedividen.relayIntents — array of supported relay intentsdividen.trustLevels — array of supported trust levelsdividen.taskTypes — self-identified task types this instance excels atendpoints — all API endpoints (a2a, federation, v2Connections, v2Relay, agentApi, docs)authentication — Bearer token scheme with dvd_ prefixAll API endpoints (except the agent card) require a Bearer token. Generate one from Settings → API Keys in the DiviDen UI. Tokens have a dvd_ prefix.
Authorization: Bearer dvd_your_api_key_here
API keys have configurable permissions: read, write,relay, a2a. Usage is tracked (count + last used).
Compatible with Google's A2A spec. Send tasks, check status, cancel.
POST /api/a2a
{
"method": "tasks/send",
"params": {
"id": "optional-external-id",
"message": {
"role": "user",
"parts": [
{ "type": "text", "text": "Review the Q2 budget proposal" },
{ "type": "data", "data": { "deadline": "2026-04-15" } }
]
},
"metadata": {
"connectionId": "optional-connection-id",
"intent": "assign_task",
"priority": "high",
"dueDate": "2026-04-15T00:00:00Z"
}
}
}Maps internally to a DiviDen relay. Returns relayId for tracking.
{ "method": "tasks/get", "params": { "id": "relay-id" } }Status maps: pending→submitted, delivered→working, agent_handling→working, user_review→input-required, completed→completed, declined→failed.
{ "method": "tasks/cancel", "params": { "id": "relay-id" } }For cross-instance relay delivery. Authenticated with federation tokens (not Bearer API keys). Two equivalent paths are supported for compatibility with both v1 and v2 protocol instances:
POST /api/federation/relay ← v1 (original) POST /api/v2/relay ← v2 (alias, same behavior)
// Header:
X-Federation-Token: <token-from-connection-handshake>
// Body:
{
"connectionId": "remote-connection-id",
"relayId": "remote-relay-id",
"fromUserEmail": "sender@their-instance.com",
"fromUserName": "Sender Name",
"toUserEmail": "recipient@this-instance.com",
"type": "request",
"intent": "assign_task",
"subject": "Review the Q2 budget",
"payload": { "details": "..." },
"priority": "high",
"dueDate": "2026-04-15T00:00:00Z"
}Effective April 18, 2026. Aligned with FVP Build 522. The inbound handler at POST /api/federation/relay applies the following processing pipeline before persisting:
Dedupes on peerRelayId + connectionId. Duplicate requests return:
{ success: true, duplicate: true, relayId: "<existing-relay-id>" } // HTTP 200A relay is treated as ambient when payload._ambient === true or payload.ambient === true or (intent === 'share_update' AND priority === 'low').
Recipient's UserProfile preferences checked in this order. First failing gate short-circuits with HTTP 200:
relayMode === 'off' → reason: 'relay_mode_off'
relayMode === 'minimal' → reason: 'relay_mode_minimal_blocks_ambient'
allowAmbientInbound === false → reason: 'ambient_inbound_disabled'
topic in relayTopicFilters[] → reason: 'topic_filtered:<topic>'
now in relayQuietHours window → reason: 'quiet_hours'
// Response shape:
{ ok: true, filtered: true, reason: '<reason>' } // HTTP 200For non-ambient relays where intent is one of ['assign_task', 'delegate', 'schedule', 'request_approval'], a KanbanCard is auto-created at the leads stage with:
KanbanCard {
status: 'leads',
sourceRelayId: <relay.id>, // back-link to the relay
// ... card fields derived from subject/description/priority
}
AgentRelay {
cardId: <card.id>, // forward-link to the card
// ... relay fields
}Both ambient and task relays surface to CommsMessage, with different defaults:
// Ambient
{ priority: 'low', state: 'read', content: 'Relay from ...', linkedCardId: null }
// Task / non-ambient
{ priority: <relay.priority>, state: 'new', content: 'Relay from ...', linkedCardId: <card.id> }{
success: true,
relayId: '<local-relay-id>',
ambient: <boolean>,
cardId: '<created-card-id-or-null>',
fallback: <boolean> // true if toUserEmail did not match a local user
}Symmetry note: all six behaviors from Jon's Comms Unification Vision now hold in both directions across DiviDen ↔ FVP. See the FVP Build 522 reply for the full audit.
When the receiving instance completes or declines a relay, it pushes the response back to the originating instance. Relay responses skip the queue and go directly into the sender's comms and chat context.
POST /api/federation/relay-ack
// Header:
X-Federation-Token: <token-from-connection-handshake>
// Body:
{
"relayId": "original-sender-relay-id",
"localRelayId": "remote-instance-relay-id",
"status": "completed",
"responsePayload": "Here is the analysis...",
"subject": "Review the Q2 budget",
"timestamp": "2026-04-15T12:00:00Z"
}On receipt: updates relay status → creates CommsMessage for sender → advances linked queue item → updates checklist delegation status → fires webhook.
Federation connection management. Supports both v1 and v2 field naming conventions with automatic duplicate detection.
GET /api/v2/connections ← list federated connections (Bearer auth) POST /api/v2/connections ← create connection request (no auth needed) POST /api/federation/connect ← v1 alias (same behavior) POST /api/federation/connect/accept ← acceptance callback (Federation token)
New in v2.1.6: The connectAccept endpoint is advertised in the agent card. When an instance auto-accepts a connection request, it POSTs {connectionId, status: "active", token} back to the requester's callback URL.
Full CRUD REST API for external agents. Bearer token auth. See theIntegration Docsor the OpenAPI spec at /api/v2/docs for full details.
GET/POST/api/v2/kanbanGET/POST/api/v2/contactsGET/POST/api/v2/queueGET/POST/api/v2/connectionsPOST/api/v2/relayPOST/api/v2/shared-chat/send┌──────────────────┐ ┌──────────────────┐
│ Instance A │ │ Instance B │
│ (OS / Platform) │ │ (OS / Platform) │
└────────┬─────────┘ └─────────┬────────┘
│ │
1. GET /.well-known/agent-card.json │
│ ─────────────────────────────>
│ (discover capabilities)
│ │
2. POST /api/v2/connections │
│ ─────────────────────────────>
│ (or /api/federation/connect)│
│ (connection request + token)│
│ │
│ 3. User B approves │
│ (or auto-accept) │
│ │
4. POST /api/v2/relay │
│ ─────────────────────────────>
│ (or /api/federation/relay) │
│ (X-Federation-Token header) │
│ (intent, subject, payload) │
│ │
│ 5. Relay delivered to │
│ User B's Divi │
│ │
│ 6. POST /api/federation/relay-ack
│ <─────────────────────────────
│ (status, responsePayload) │
│ (skips queue → comms only) │
│ │
7. GET /api/federation/jobs │
│ ─────────────────────────────>
│ (fetch network-visible jobs)│
│ │Federated instances can share open job listings across the network. Jobs with visibility: "network" are eligible for cross-instance discovery.
Auth: x-federation-token header. Federated jobs appear locally with a [InstanceName] prefix and source provenance.
You control exactly how relays reach you. Configure these in Settings → Relay.
Controls overall relay volume. "full" receives everything. "selective" filters by intent/topic. "minimal" only receives direct requests. "off" blocks all incoming relays.
Whether other agents can send you low-priority ambient relays that Divi weaves into conversation.
Whether your Divi can proactively send ambient relays to your connections.
Whether you receive broadcast relays (sent to all connections at once).
Opt out of specific topics. Example: ["sales", "recruiting"] — relays tagged with these topics are silently dropped.
The target instance has inbound federation disabled. Ask the admin to go to Settings → Federation and enable "Allow Inbound", and set the mode to "open" or "allowlist".
The target instance uses allowlist mode and your instance URL isn't registered. Ask their admin to add your URL in Settings → Federation → Known Instances.
Make sure you're hitting the correct DiviDen instance URL. The /.well-known/agent-card.json endpoint is public and should not require authentication. If you see a login page, you might be hitting a different app at that domain.
Check: (1) Connection status is "active" on both sides. (2) Recipient's relay mode is not "off". (3) If ambient, recipient has "Allow Ambient Inbound" enabled. (4) The relay topic isn't in their topic filters.
The API key user has no active connections. Create a connection first (via the UI or POST /api/connections), then retry. Or pass metadata.connectionId to target a specific connection.
The X-Federation-Token header is missing or doesn't match any active federated connection. Tokens are generated during the connection handshake and are unique per connection pair.
Teams and Projects add an organizational layer to the federation protocol. Connections gain context by being added to teams (persistent groups) or projects (scoped, goal-based collaborations).
A Team is a persistent group of connections — e.g., “Denominator Ventures team”. Team members can be local users or federated connections from other DiviDen instances. When routing tasks or broadcasting, specifying a teamId restricts the scope to team members and gives them a +5 priority boost in skill matching.
A Project is a scoped collaboration — e.g., “Series A fundraise”. Projects can belong to a team or be independent. Project members get a +10 priority boost in skill matching. Kanban cards and queue items can be associated with a project via projectId.
Federated connections (users on other OS instances) join teams/projects via their connectionId. The system distinguishes between local members (userId) and federated members (connectionId). Both participate equally in scoped broadcasts, task routing, and relay delivery.
GET/POST /api/teams — List or create teams
GET/PUT/DELETE /api/teams/[id] — Manage a team
POST/DELETE /api/teams/[id]/members — Add/remove members (local or federated)
GET/POST /api/projects — List or create projects
GET/PUT/DELETE /api/projects/[id] — Manage a project
POST/DELETE /api/projects/[id]/members — Add/remove members
• task_route + teamId/projectId → skill matches prioritize scope members
• relay_broadcast + teamId/projectId → sends only to scope members
• relay_ambient + teamId/projectId → tags relay with scope context
• Routing priority: project members (+10) → team members (+5) → all connections (base score)
As of v2.3.2, teamId and projectId travel as top-level fields on every relay pushed to POST /api/federation/relay (and /notify). The receiving instance runs local scope resolution — if the referenced team/project exists, it’s attached to the created AgentRelay + QueueItem. If not (e.g. the peer doesn’t know about your project), the scope is dropped silently and echoed back as scopeDropped in the ack response so your UI can surface the miss.
• Project implies team — if project resolves, its team also resolves automatically (inheritance).
• Ambient gating accepts object filters: { teamIds: [...], projectIds: [...] } in addition to legacy string-array tags.
• Federated project invites (v2.3.1 four-signal pattern) now correctly push over the wire — the cross-instance gap is closed.
→ Full wire details: relay-spec §7.6 Scope resolution.
Instance self-registration allows DiviDen OS instances to register with the platform (dividen.ai) using a pre-authorized connect token. This replaces the manual instance setup flow with a single API call.
Developers generate connect tokens from the Developer Portal under the Instances tab, or by clicking the Divi tag on an existing instance. Tokens are prefixed withfct_ and expire after 24 hours.
POST /api/developer/connect/tokens
Authorization: Bearer dvdn_your_api_key
Content-Type: application/json
{"instanceId": "inst_abc123"}
Response includes token,expiresAt, andinstanceId.
Set the connect token as an environment variable on the OS instance before starting the registration process:
# .env or docker-compose environment
DIVIDEN_CONNECT_TOKEN=fct_abc123...
DIVIDEN_PLATFORM_URL=https://dividen.ai
The instance reads this token at startup and uses it to authenticate with the platform during the registration handshake.
The instance sends a POST to the platform's federation register endpoint with its metadata and the connect token:
POST /api/federation/register
Content-Type: application/json
{ "connectToken": "fct_abc123...", "instanceUrl": "https://my-instance.example.com", "instanceName": "My DiviDen Instance", "version": "2.5.131", "capabilities": ["relay", "a2a", "widgets"] }
Instances that present a valid, unexpired connect token are auto-trusted -- the platform skips the manual approval step and immediately returns:
Without a valid token, the registration enters the standard pending-approval queue and requires admin action.
• Active -- Token generated, not yet used. Expires after 24 hours.
• Used -- Token consumed during registration. Cannot be reused.
• Expired -- Token passed its 24-hour TTL without being used.
• Revoked -- Token manually revoked by the developer from the portal.
Token status is visible in the Developer Portal on the instance detail page. Developers can generate new tokens for expired or revoked instances.
Download a plain-text copy of this page
Last updated: May 30, 2026
Open source: github.com/Denominator-Ventures/dividen
OS docs & self-hosting: dividen.ai/open-source