← Back to Blog
Architecture13 min read

How DCP Works: The Permission Layer Between AI Agents and Your Secrets

How DCP works, explained from the code: the permission layer between AI agents and your keys, credentials, and money. What tools agents get over MCP, how budgets and approvals are enforced, and how remote agents pair with your desktop.

how dcp worksai agent securityagent permissionsmcpcredentialsagent payments
Share:

AI agents need access to real things: API keys, credentials, personal data, and money.

The standard advice is to never hand them raw secrets. Good advice. But almost nobody explains what the alternative actually looks like at the protocol level.

This post does. It is a full walkthrough of how DCP works under the hood: where secrets live, how the encryption works, what tools agents get, how budgets and approvals are enforced, and how remote agents connect. DCP is open source, so if you want to verify anything in this post, the code is public.

The short version:

DCP is a permission layer that sits between AI agents and your sensitive resources. Your secrets live in an encrypted vault on your own machine. Agents connect over MCP and request actions. DCP checks the agent's permissions, budget, and your approval policy, then performs the action itself. Secrets are decrypted in memory for milliseconds, used, and wiped. The agent only ever sees the result.

Now the long version.

What Is DCP?

DCP (Delegated Custody Protocol) is an open source permission layer for AI agents. It stores your credentials, API keys, personal data, and wallet in one encrypted local vault, and lets agents request specific actions instead of holding raw secrets themselves.

The core contract:

Agents get capabilities. Users keep custody.

DCP ships as a desktop app plus a set of open source packages:

  • @dcprotocol/core handles types, crypto, storage, and the budget engine
  • @dcprotocol/vault is the local vault server and policy engine, bound to 127.0.0.1:8421, localhost only
  • @dcprotocol/agent is the MCP server agents connect to, over stdio or HTTP, plus remote pairing
  • @dcprotocol/relay is an encrypted message bus that connects cloud agents to your desktop vault
  • @dcprotocol/telegram adds optional approval notifications with Approve and Deny buttons in Telegram

Here is the whole system in one picture:

 Local agents                          Remote agents
 (Claude, Cursor, VS Code)             (VPS, OpenClaw, workers)
        |                                     |
        | MCP (stdio / HTTP,                  | end-to-end encrypted
        | localhost only)                     | relay envelopes
        v                                     v
 +--------------------------------------------------+
 |              DCP Vault  (127.0.0.1)              |
 |                                                  |
 |   auth -> scopes -> budgets -> consent -> act    |
 |                                                  |
 |   encrypted storage: keys, credentials, data     |
 +--------------------------------------------------+
        |
        | approval requests
        v
 Desktop popup  /  Telegram Approve / Deny

One design decision matters more than all the others: the vault server only binds to localhost. It is never exposed to the network. Remote agents reach it through an encrypted relay, never directly.

How Is the Vault Encrypted?

The vault uses envelope encryption with modern, well audited primitives.

  • Cipher: XChaCha20-Poly1305 authenticated encryption, 256-bit keys, a fresh 192-bit random nonce per encryption
  • Key derivation: Argon2id with a 64 MB memory cost and 3 iterations, deliberately expensive so brute forcing a passphrase stays slow even on GPUs
  • Recovery: a 12-word BIP-39 phrase, shown once at setup and never stored in the vault

Every record gets its own random 256-bit data encryption key (DEK). That DEK is then wrapped by a master key that lives outside the database:

 your data
     |  encrypted with a per-record DEK
     v
 ciphertext  ------------------> stored in SQLite

 per-record DEK
     |  wrapped with the master key
     v
 wrapped DEK ------------------> stored next to the record

 master key  ------------------> OS keychain
                                 (hardware-backed on macOS,
                                  0600-permission file fallback)

Why two layers? The master key never touches the database, one compromised record exposes nothing else, and key rotation does not require re-encrypting the whole vault.

Where do the most sensitive keys live?

Wallet keys, passports, and API credentials are just encrypted records like everything else, tagged with a sensitivity level of critical or sensitive. When an approved operation needs one, the vault:

  1. Unwraps the record's DEK with the master key
  2. Decrypts the secret in memory
  3. Performs the operation, for example producing a signature
  4. Immediately wipes the secret with sodium_memzero(), a zeroization call the compiler cannot optimize away

The decrypted secret exists for a few milliseconds. It is never written to disk unencrypted, never logged, never sent over any connection, and never returned to an agent through any code path.

What Tools Do Agents Actually Get?

Agents connect to DCP through MCP, the same protocol Claude Desktop, Cursor, VS Code, and OpenClaw use for tools. The tool surface comes in three tiers, sorted by how much damage each tier could do.

Read-only tools, no approval needed:

  • vault_get_address returns the wallet's public address
  • vault_get_balances returns current wallet balances
  • vault_get_tx_status checks a transaction by signature
  • vault_get_tx_history returns recent transaction history
  • vault_search_tokens searches the token list by symbol, name, or mint
  • vault_budget_check answers whether an amount would pass the limits
  • vault_scope_guide returns the canonical list of data scope names

Data tools, governed by per-agent scopes:

  • vault_read reads scoped personal data, like an API key or a shipping address
  • vault_write stores scoped data, and always requires consent

Wallet and payment tools, governed by budgets and approval thresholds:

  • vault_sign_tx signs a transaction with the vault wallet
  • vault_sign_message signs a wallet message
  • vault_sign_x402 signs an x402 payment payload for pay-per-request APIs
  • vault_transfer builds, signs, submits, and confirms a transfer
  • vault_swap executes a token swap

Notice the shape of this API. An agent can check anything freely: its address, balances, whether an amount fits the budget. The moment it wants to act, it crosses into policy territory. That split is intentional. Agents plan without friction and act only with permission.

How Do Scopes and Per-Agent Permissions Work?

Everything in the vault lives under a hierarchical scope name:

identity.email
address.shipping
credentials.api.openai
credentials.api.github
crypto.wallet.*
preferences.diet

Each connected agent has its own list of permitted scopes, and wildcards are supported:

  • identity.* grants all identity data
  • read:* grants every read operation and no writes
  • * grants everything, which you almost never want

So your coding agent can have credentials.api.github and nothing else. Your shopping agent can have address.shipping and preferences.*. Your payments agent can have signing access with a tight budget. Same vault, different keys to different doors.

Every scope also carries a sensitivity level: standard, sensitive, or critical. The policy engine treats a passport differently from a T-shirt size.

One more detail that matters. The vault's policy database is the single source of truth. Permissions are not baked into tokens the agent holds. When you revoke an agent, revocation is immediate, because there is no token floating around that still works.

What Happens When an Agent Asks to Act?

This is the heart of DCP. Say an agent calls vault_transfer for 5 USDC. Every request goes through the same pipeline:

 agent request
     |
     v
 1. verify request signature (Ed25519) ---- invalid? -> rejected
     |
     v
 2. scope check ---------------------- not granted? -> denied + logged
     |
     v
 3. budget check
     |    per-transaction limit ------ too big?  -> BUDGET_EXCEEDED_TX
     |    rolling daily limit -------- over cap? -> BUDGET_EXCEEDED_DAILY
     v
 4. approval threshold
     |    below threshold -> proceed
     |    above threshold -> pending consent
     |                       desktop popup or Telegram
     |                       expires in 5 minutes if ignored
     v
 5. execute inside the vault
     |    decrypt key, act, zeroize
     v
 6. immutable audit log
      GRANT / READ / EXECUTE / DENY / REVOKE

Some real defaults from the code: 1 USDC per transaction, 5 USDC per rolling day, all configurable per currency and per agent. While a consent is pending, the agent polls every 2 seconds for the outcome. No answer within 5 minutes means no.

There is also a rate limiter on top of all of this: 5 executions per minute per agent session, and 5 failed unlock attempts trigger a 5 minute lockout on the vault itself.

Does auto-approve defeat the purpose?

No, because of what it is allowed to cover.

You can grant an agent a standing approval for specific data scopes, say credentials.api.openai for your coding agent, so it is not prompting you forty times a day. Standing grants last 90 days and are listed, reviewable, and revocable.

Signing and payments are deliberately excluded. There is no blanket switch that always approves spending. Money movement is always bounded by the budget engine and the approval threshold. Small amounts inside your limits flow without friction. Anything above the line asks a human. That is the whole design philosophy in one rule.

How Do Remote Agents Connect Without Exposing the Vault?

Local agents talk to the vault over localhost. Easy.

But real agent workloads increasingly run on a VPS: a personal OpenClaw agent, a monitoring bot, an automation worker. Those machines cannot reach localhost on your laptop, and you should never port-forward a vault to the public internet.

DCP solves this with a relay and a pairing ceremony:

 Desktop                    Relay                     VPS agent
    |                         |                           |
    |-- 1. generate invite ------------------------------>|
    |    (vault id, relay URL,                            |
    |     vault public key, expiry)                       |
    |                         |    2. agent generates     |
    |                         |       its own keypair     |
    |                         |<-- 3. signed claim -------|
    |<-- 4. claim arrives ----|--- 5-word phrase -------->|
    |                         |                           |
    |   5. both screens show the same 5-word phrase       |
    |      user compares, then approves on desktop        |
    |                         |                           |
    |-- 6. approval --------->|--- agent_id ------------->|
    |                         |                           |
    |<========= end-to-end encrypted requests ===========>|

The 5-word verification phrase is the anti-phishing step. If the words on your desktop match the words on the server, you know you are approving that machine and not an attacker who intercepted an invite. Cheap for humans, expensive for phishers.

After approval, every request the remote agent makes is signed with its own keypair and checked against its own scopes and budgets. A remote agent gets no special powers over a local one.

And the part I like most: the relay cannot read any of it. Agent traffic is end-to-end encrypted with HPKE (X25519) using the vault's public key from the invite. The relay routes opaque encrypted envelopes. It cannot see scopes, amounts, or data. It also pins each vault ID to its key on first use, so a different key claiming your vault ID gets rejected. Even a fully compromised relay cannot impersonate your vault or read your traffic.

How Do Agent Payments Work?

Agents are starting to pay for things: metered APIs, data access, services priced per request. The x402 standard handles this over plain HTTP, and DCP gives it a permission boundary.

vault_sign_x402 takes a base64-encoded payment payload plus display metadata (amount, currency, recipient, purpose), runs it through the same budget and approval pipeline as every other spending operation, and returns a signature the agent attaches to its request.

Two properties are worth calling out:

  • The payload is immutable. The vault signs exactly the bytes it receives. If anything rewrites the payload along the way, the signature simply fails to verify on the other end. There is no code path where the vault edits a payment.
  • The vault does not submit the payment. It signs. The agent handles the network request. Signing authority and network activity stay separated.

This is what makes agent payments workable in practice. Your agent can pay a metered API forty times a day inside a small budget without asking you once, and the forty-first request that crosses the line becomes an approval on your phone instead of a surprise on your statement.

Real Use Cases

Theory is nice. Here is what people actually do with this.

The coding agent with scoped credentials

Claude Code or Cursor needs your GitHub token and an OpenAI key. Instead of pasting them into config files across five projects, they live in the vault under credentials.api.github and credentials.api.openai. The agent reads them through vault_read, covered by a standing grant. Every read is logged. If the agent misbehaves or your laptop policy changes, you revoke once, because the credentials were never scattered in the first place.

The API-paying research agent

A research agent pays per request for a data API through vault_sign_x402. Each payment is tiny and flows automatically under the approval threshold, hard capped by the daily budget. If a prompt injection convinces the agent to send a large payment to a malicious endpoint, the budget engine rejects it before any human needs to notice, and the attempt lands in the audit log.

The remote personal agent

An OpenClaw agent runs around the clock on a VPS, handling tasks that need your context: addresses, preferences, small payments. It paired via invite and verification phrase, talks to your desktop vault through the encrypted relay, and holds zero secrets on the server. If the VPS is ever compromised, the attacker gets a revocable agent keypair. Not your keys, not your data.

The spending agent on a leash

An agent automates purchases or transfers through vault_transfer. Per-transaction and daily caps keep it bounded. Anything above threshold pings your phone with an approval request, and you tap Approve or Deny in Telegram. The agent gets speed inside the box. You hold the box.

Many agents, one vault

The end state is not one agent. It is five or ten: reasoning, coding, research, payments, automation. With DCP that is one vault, one place to look, and a different scope list and budget per agent. Adding an agent is a pairing, not another copy of your secrets. Removing one is a revoke, not a key-rotation weekend.

Threat Model, Honestly

No system removes risk. Good systems bound it.

ThreatRaw secrets in configsWith DCP
Prompt injectionAgent acts immediately, no limitBudget caps, approval threshold, audit trail
Agent bug or bad tool callUnlimited blast radiusBounded by per-transaction and daily limits
Compromised VPSSecrets are stolenOnly a revocable agent keypair is stolen
Compromised relayNot applicable, vault exposed insteadSees only encrypted envelopes, key pinning blocks impersonation
Secret sprawlKeys copied into N config filesSecrets live in one encrypted vault
No visibilityNo record of agent actionsImmutable audit log

What DCP does not protect against: an attacker who has your unlock passphrase and physical control of your unlocked machine, or approvals you tap without reading. The human gate only works if the human reads the prompt. That will stay true of every approval system ever built.

FAQ

Does the AI agent ever see my private keys or credentials?

Keys, no, never. There is no tool or code path that returns key material to an agent. Credentials are different: an agent with an approved scope can read the credentials you granted it, and every read is logged and revocable. Signing keys stay inside the vault permanently.

What encryption does DCP use?

XChaCha20-Poly1305 authenticated encryption with envelope encryption, a random 256-bit key per record wrapped by a master key in the OS keychain, Argon2id for passphrase derivation, Ed25519 for request signatures, and X25519 HPKE for relay traffic.

Can agents spend without my approval?

Only inside limits you set. Per-transaction caps, rolling daily caps, and an approval threshold are enforced per currency on every spending operation. Above the threshold, a human must approve. There is no way to auto-approve spending wholesale.

Does DCP work with Claude Desktop, Cursor, and OpenClaw?

Yes. Anything that speaks MCP, over stdio or HTTP, can connect: Claude Desktop, Cursor, VS Code, OpenClaw, and custom clients. Remote agents on a VPS connect through the encrypted relay after pairing.

Is the relay a custodian?

No. The relay routes end-to-end encrypted envelopes it cannot decrypt. Keys and policy decisions never leave your machine. If the relay disappeared tomorrow, local agents would be unaffected and remote agents would reconnect through another relay.

Which chains does the wallet support?

Wallet signing currently supports Solana, and the vault, scopes, budgets, and approval system are chain-agnostic by design. A dedicated deep dive on the wallet side is coming next.

Is DCP open source?

Yes. The protocol, vault, agent, relay, and Telegram packages are all open source. You can verify every claim in this post in the code: github.com/1lystore/dcp.

The Bottom Line

The gap between agents that chat and agents that work is trust infrastructure.

Not better models. Not more tools. A boundary you can actually reason about: encrypted custody, scoped permissions, hard budgets, human approval above the line, and a log of everything.

That is what DCP is. Not a cage for agents, but the thing that makes it reasonable to hand them real work.

Give AI agents permissions. Not your keys.

Download DCP Desktop at dcpagent.com, or start with the getting started guide and the architecture docs.

Iftakhar Rahmany

Written by

Iftakhar Rahmany

Ready to secure your AI agents?

DCP gives agents permissions, not keys. Download free and open source.

Download DCP