Tvijo wiki
Catalog

Topics

Keep provider keys out of the agent: one gateway, one token per task

If an agent can read your provider key, you cannot say who spent what. Put the key in one process, and give each task a token that names the task, carries its budget and dies with it. Then every cost has an owner and a stolen token is worth little.

🎯 For A developer who lets agents call paid model APIs

πŸ“š You will learn
  • Why a key in the agent's environment breaks attribution
  • How a per-task token with a budget works
  • What to store and what never to store

πŸ”‘ The problem with a shared key

The easy setup puts the provider key in an environment file, and every script and agent reads it. It works, and it makes three things impossible. You cannot say which task made a call, because they all look the same to the provider. You cannot stop one task without stopping all of them. And any agent that can read its own environment can leak the key through a prompt.

Our own measurement in September 2026 found this still happening in one bridge runner that sourced the environment file directly. That finding is why the design below exists.

πŸ—οΈ The design

One small service holds the provider keys. It is the only code in the system that reads them, and a test scans the code to prove that no other module does. Agents never see a key. They call the service and present a token.

The token is issued for one task. It is tied to a fingerprint of the task packet, so it cannot be reused for a different job. It carries a budget and a per-call ceiling, an expiry time, and it is closed when the task ends. The service stores only a hash of the token, never the token. Each call is a row in the ledger with the task id, so spend has an owner.

The service also keeps its own books separate from other money paths. It does not import the trading code, and a test checks that.

πŸ“Š In numbers

Since 2026-09-21 the service has issued 1,415 task tokens. 1,367 are closed and 48 are not marked closed, some of them in flight or abandoned and waiting for expiry. There are 4 budget reservations. The test file for the module boundaries holds 17 tests.

πŸ› οΈ Practice: move the key out of the agent

  1. Find every place a provider key is read: environment files, config files, scripts. List them.
  2. Create a small service that holds the keys and exposes the same call interface your agents already use.
  3. Issue a token per task. Bind it to a hash of the task description or packet, a budget, a per-call maximum and an expiry.
  4. Store the token hash only. Show the token once to the caller.
  5. Log every call with the task id, model, tokens and cost, including retries and fallbacks.
  6. Add a test that scans your code and fails if any other module reads the key variable.
  7. Remove the key from every agent environment and from every shell profile that agents inherit.

βœ… Check yourself

  • Print the environment of an agent process. No provider key appears.
  • Use a task token after the task is closed. The call is refused.
  • Use a token with a different packet. It is refused.
  • For any call in last week's ledger, name the task and its budget.

🚧 When this does NOT work

  • The gateway becomes the single point of failure. If it is down, no model call works. Run it as a managed service with a restart policy.
  • Keys elsewhere. If a developer's shell profile still exports the key, the agent inherits it. Audit shells too.
  • Tokens with long life. A token that lives a week is a key with extra steps. Tie it to the task.
  • A single provider outage. The gateway does not remove it. Decide your fallback policy and log fallbacks.
  • Local models. A model on your own hardware has no key. You still want the ledger.

πŸ“Š Evidence

What we measured Task tokens issued and closed, reservations, and tests for module boundaries
When 3 November 2026, 21:53 UTC
Artifact The task token and reservation tables of our transport database, the credentials module and its boundary tests in our private repository
Limit The count shows use, not security. A review by someone outside the team has not been published

➑️ Next

See how budgets are reserved before a task runs in Costs, budgets and limits, and what to check in a connection in the MCP server security checklist.

Sources

πŸ”— Article connections

Open the full knowledge graph β†—

Published article links. Select a node to open its article at the heading.

100%
β†’ Linked articles← Linked fromβ‹― Same topic
Article links Β· keyboard / text view

πŸ’¬ Comments

Comments are public and moderated. Do not post personal data.
  • No comments yet. Be the first!

Next steps