Skip to main content
The data-plane agent is a small container that runs inside your network and executes tools for your organization’s local_only services. Danube’s control plane keeps doing policy, routing, metering and audit, but it never makes the credentialed call and never receives your secrets. It queues an un-credentialed dispatch (tool definition, parameters and credential references); the agent resolves the references locally, makes the call and reports the outcome back. The data plane is included with the Team and Enterprise plans. An owner or admin of an organization on either plan can enroll an agent from the dashboard; nothing needs to be enabled for you.

Quick start

1

Generate an enrollment token

Go to Dashboard > Systems > Data plane and click Generate enrollment token. Tokens are valid for one hour and single use: two agents started with the same token yield one enrolled agent and one refused. Admins and owners only.
2

Run the agent

The image is published to ghcr.io/danubeai/dataplane-agent with three kinds of tag: latest, the agent version (for example 0.4.0) and sha-<short> for the exact commit. Pin the version tag in production.On first boot the agent exchanges the token for a durable identity (an agent id and secret) and writes it to the /data volume. Restarts reuse it and the token is not needed again, which is why the volume and the restart policy are in the command: without the volume a restart would enroll a new agent every time.
3

Confirm it is online

The agent appears in the Data Plane page within a few seconds of its first poll, with the version it is running and an Online badge. An agent that stops polling for 90 seconds shows Offline; calls to the organization’s local_only tools then fail at once with no_dataplane_agent instead of waiting for the dispatch budget. Revoke an agent from the same page at any time; a revoked agent is rejected on its next request.
4

Store credentials as references

Data-plane execution needs credentials stored as references, not values: env://VAR_NAME for an environment variable on the agent’s host, or vault://<mount>/<path>#<field> for HashiCorp Vault (KV v2). A credential held only as a value in Danube is never shipped to the agent; the dispatch fails with credential_reference_unresolved telling you to re-store it as a reference.

Configuration

Network

The agent makes outbound HTTPS calls only: to DANUBE_API_URL to poll for work, report results and stream audit events, and to the hosts of the tools it runs. It listens on no port, so nothing has to be opened inbound and no public address is needed.
  • Egress allowlist. If your network restricts egress, allow api.danubeai.com on 443 plus the hosts of your internal services. DANUBE_ALLOWED_DESTINATIONS is the agent-side counterpart: it refuses a dispatch whose host is not on the list, so a tool definition edited to point elsewhere cannot make the agent call it.
  • Proxy. Set HTTPS_PROXY (and NO_PROXY for internal hosts that should be reached directly).
  • Private CA. Mount your CA bundle into the container and point SSL_CERT_FILE at it. The agent does not disable certificate verification.

Several agents

An organization can enroll any number of agents; each enrollment uses its own token. Dispatches are claimed by whichever agent polls first, so running two or more agents gives you throughput and lets one restart without a gap. Within one agent, DANUBE_MAX_CONCURRENCY sets how many dispatches it runs at once; the default is four, and one is the right setting for an internal service that cannot take parallel load. Each agent shows its own online state and version in the dashboard, and the version updates on the next poll after you deploy a new image.

Data handling

Two organization settings, under Organization > Settings (owner or admin), decide what Danube keeps about data-plane calls. The same card holds Hosted AI can use internal tools, which is about prompts rather than storage and is described under Organizations; the audit log retention sits in the same card and is described under Audit Log.
  • Store execution payloads. On by default. Off is residency mode: the request parameters and the result of a data-plane call are never written to Danube’s database. The dispatch row keeps the request only until an agent has claimed it (it is the transport queue) and then holds {"stored": false}; the result is recorded as {"stored": false, "sha256": ..., "bytes": n}, a hash of the canonical JSON and its size, and the execution log stores the same digest for both the request and the result. The caller that made the request still receives the full result; only Danube’s copy is withheld. Status, timing, the error text and the error type are kept either way, since the dashboard and the reliability numbers read them.
  • Keep execution history. Indefinitely, or 30, 90 or 365 days. With a retention set, a nightly job deletes the organization’s execution rows older than that, in batches, so a large backlog is drained over several nights rather than in one long transaction.
Dispatch rows themselves are purged hourly once they are a week past completion, and the replay-protection nonces after a day, regardless of these settings.

How failures are attributed

Every failed call carries an error_type and a fault (caller, upstream or danube), on the data plane like everywhere else. The agent classifies what it saw and the control plane passes that through unchanged, so a 404 from your internal service is not_found and a rejected body is bad_request, not a generic data-plane error. Only upstream failures move a tool’s reliability score. A caller failure, an offline agent included, is reported next to it and never pushes agents away from a working tool.

MCP servers

A remote MCP server inside your network can be registered as local_only like an HTTP service: pick Runs inside your network in Create Tools, or send {"source": "mcp", "visibility": "local_only", "mcp": {"server_url": "http://mcp.internal:8080/mcp", "transport": "http", "auth_type": "bearer"}} to POST /v1/organizations/{org_id}/services. Danube never connects to the server, so the address does not have to be reachable from the internet and is not checked against the outbound-address policy; the agent’s DANUBE_ALLOWED_DESTINATIONS is what gates it.
  • Transports. Streamable HTTP (transport: "http"; the agent keeps the server’s Mcp-Session-Id and ends the session when the call is done) and the older HTTP+SSE transport (transport: "sse"; the agent opens the event stream, posts messages to the endpoint the server names and reads replies off the stream). The agent initializes with protocol version 2025-06-18 and falls back to 2024-11-05 when the server refuses it. A local (stdio) MCP server, a subprocess rather than a URL, cannot be registered for an organization.
  • Authentication. auth_type is none, bearer (Authorization: Bearer), api_key (the header named by auth_config.header_name, X-API-Key by default) or basic. The credential is stored as a reference like any other data-plane credential: env://MCP_TOKEN or a vault:// path in the value field (username and password for basic). The agent resolves it and builds the header; the control plane ships the auth type and the header name only. A {api_key} placeholder in the server URL is filled from the reference too, with no header sent.
  • Tool discovery runs through the agent. Right after registration, and again from Refresh tools on the service page, Danube queues a tools/list dispatch instead of connecting itself. The service shows Discovering tools while it runs. With no agent online the sync records no_dataplane_agent and the service page says so; start an agent and refresh. The daily catalog reconcile that keeps public MCP services current does not touch organization services, so Refresh tools is how a renamed or added tool reaches the catalog.
  • Results. A call returns the MCP result envelope (content, structuredContent, isError) as the tool’s result, redacted by the agent before it leaves your network. An isError result is reported as upstream_rejected with the server’s text; a tool the server no longer offers is upstream_tool_missing.

Security model

  • Secrets never leave your network. Dispatches carry credential references only. The agent resolves them in-process at call time.
  • Signed requests. Every agent request is authenticated with HMAC-SHA256 over the method, path, timestamp, nonce and body hash, using the agent secret. Requests with more than 300 seconds of clock skew, or a reused nonce, are rejected.
  • Revocation. An admin can revoke an agent at any time.
  • Spend limits fail closed. The agent syncs your organization’s API key spend caps and enforces them before each call. If its snapshot is older than the staleness threshold and cannot be refreshed, execution is denied, not allowed.
  • Audit stream. Every execution and denial is sent to the audit log with a per-agent sequence number, buffered and retried, and ingested idempotently. The control plane writes its own tool.execute row for every reported result (actor_type: dataplane, with duration_ms, spend_cents and payloads_stored in the metadata). A result that arrives after the control plane has already expired the dispatch is accepted and audited as a late result rather than treated as an error.
  • Results are masked twice. The agent masks credential values in a result before it leaves your network; the control plane runs the same pass on receipt in case an older agent did not.

Limits in this release

  • Remote servers only. HTTP tools and remote MCP servers (streamable HTTP or SSE) run over the data plane; a local (stdio) MCP server does not, since it is a subprocess rather than an address. OAuth-authenticated services are not supported over the data plane either, since the token refresh runs in the control plane; an OAuth-protected MCP server needs a token stored as a reference.
  • 60 second dispatch budget. The control plane waits 60 seconds for an agent to report; a longer call is marked dataplane_timeout and its late result is recorded in the audit log but not returned.
  • Supported credential injection: bearer or HTTP auth header, API key header, API key query parameter; for MCP servers bearer, API key header and basic.

Operations

  • Logs go to stdout: docker logs danube-dataplane.
  • The image carries a health check that fails when the agent has not completed a poll in DANUBE_HEALTH_MAX_AGE_SECONDS, so an orchestrator restarts a wedged agent on its own.
  • Graceful shutdown on SIGTERM or SIGINT: in-flight dispatches finish and the audit buffer is flushed.
  • Network errors back off exponentially, from 1 second to a 60 second cap.