Veefore docs

Broker a credential

Take the secret out of the agent entirely — including the material-key mistake that fails two layers from its cause.

The highest-value change you can make. An agent that holds an API key has that key in its prompt context, its logs, and whatever the model says next. Move it into the broker and prompt injection stops being credential theft.

#Register the credential

bash
curl -X POST https://veefore.example.com/v1/credentials \
  -H "Authorization: Bearer $VEEFORE_API_KEY" \
  -H 'content-type: application/json' \
  -d '{
    "key": "payments-api-key",
    "name": "Payments service API key",
    "type": "API_KEY",
    "provider": "local",
    "material": {
      "api_key": "sk_live_…",
      "header": "x-api-key"
    }
  }'

The response is metadata. No endpoint ever returns the material.

#Get material right

This is the mistake that costs an afternoon

Each credential type reads specific keys from material and discards the rest. Put the secret under a name the broker does not read and the failure appears two layers from its cause: Veefore seals and stores it, permits the action, brokers nothing usable, and your downstream returns 401. Nothing in the Veefore logs looks wrong, because from Veefore's point of view nothing was.

Veefore now refuses this at registration and at rotation with INVALID_CREDENTIAL_REFERENCE rather than letting you find out in production.

Type Reads
API_KEY api_key / apiKey / key / value, plus optional header, prefix
BEARER_TOKEN token / access_token / value
BASIC_AUTH username and password
DATABASE_DSN dsn / url / connection_string
OAUTH_CLIENT client_id and client_secret
MTLS_CERTIFICATE certificate and private_key
SIGNING_KEY private_key and algorithm

BASIC_AUTH, MTLS_CERTIFICATE and SIGNING_KEY are exempt from the single-secret check because their material is legitimately multi-field.

header and prefix control how an API_KEY is presented downstream:

json
{ "api_key": "sk_live_…", "header": "x-api-key" }
{ "api_key": "sk_live_…", "header": "authorization", "prefix": "Bearer " }

#Attach it to a tool

bash
curl -X POST https://veefore.example.com/v1/tools \
  -H "Authorization: Bearer $VEEFORE_API_KEY" \
  -H 'content-type: application/json' \
  -d '{
    "workspace_id": "wsp_01JAV…",
    "key": "refund_customer",
    "name": "Refund a customer order",
    "kind": "HTTP",
    "required_capability": "refund.create",
    "endpoint_url": "https://payments.internal.example.com/refunds",
    "destination_allowlist": ["payments.internal.example.com"],
    "credential_id": "cred_01JAV…"
  }'

That is the whole integration. The agent never references the credential, never receives it, and does not need to know it exists.

#What happens at request time

Stage 10 of the pipeline — after authentication, identity, lifecycle, capability, delegation, policy, risk and approval have all passed:

  1. The broker unseals the material.
  2. It issues a lease: a short-lived credential scoped to this action.
  3. The tool runtime injects it into the outbound request.
  4. The lease is recorded by reference and expires.

Default lease lifetime is CREDENTIAL_DEFAULT_TTL_SECONDS, 600 seconds. Lease statuses: ISSUED, USED, EXPIRED, REVOKED.

Why stage 10 and not earlier

Brokering is the first irreversible step. Everything before it can refuse with no trace outside Veefore.

Putting the broker last is what makes BLOCK mean blocked. Brokering earlier — say, for latency — would mean a blocked action had already caused a credential to be issued, and "we blocked it" and "the secret did not go out" would become two different claims with only one of them true.

#Migrating an agent that already holds a key

Register the existing key as a credential

Same value, under the right material key for its type.

Attach it to the tool and authorize the agent

The agent can now reach the downstream through Veefore.

Switch the agent's calls to `act()`

Where it previously called your API directly with the key, it now calls agent.act({ tool: 'refund_customer', … }).

Remove the key from the agent's environment

This is the step that actually achieves something. Until you do it, the agent still holds a usable credential and nothing has improved.

Rotate

The old value was in an agent's environment, possibly in its logs, possibly in a model provider's request history. Treat it as exposed.

bash
curl -X POST https://veefore.example.com/v1/credentials/cred_01ABC/rotate \
  -H "Authorization: Bearer $VEEFORE_API_KEY" \
  -H 'content-type: application/json' \
  -d '{ "material": { "api_key": "sk_live_NEW…", "header": "x-api-key" } }'

#Rotation and revocation

Rotation invalidates every outstanding lease, so an in-flight action holding an old lease fails rather than continuing with a credential you decided to retire. Status moves through ROTATING while it happens.

bash
curl -X POST https://veefore.example.com/v1/credentials/cred_01ABC/revoke \
  -H "Authorization: Bearer $VEEFORE_API_KEY" \
  -H 'content-type: application/json' \
  -d '{ "reason": "Key published in a support ticket" }'

Revocation is immediate. Every tool depending on the credential starts failing at stage 10 with INVALID_CREDENTIAL_REFERENCE.

Both credential:rotate and credential:revoke require step-up authentication, and credential:revoke is high impact.

#Diagnosing a downstream 401

Veefore allowed the action and your downstream rejected what it received. In order of likelihood:

  1. Wrong material key for the type. api_key versus token versus key. Now caught at registration, but an older credential may predate the check — rotate it and the check runs.
  2. Wrong header. Your downstream wants x-api-key, you configured authorization, or vice versa.
  3. Missing prefix. authorization usually needs Bearer including the trailing space.
  4. The key itself is wrong or revoked downstream.

veefore logs --limit 20 shows the stage results. A CREDENTIAL stage of PASS with an EXECUTION stage carrying http_401 means Veefore brokered something and your downstream did not accept it — which narrows it to the first three.

#Providers

CREDENTIAL_BROKER_PROVIDER selects the backend. local seals material in PostgreSQL with VEEFORE_DATA_ENCRYPTION_KEY, which is right for development and for deployments where the Veefore database is already your trust boundary.

For production, point it at your existing secret manager so material lives where the rest of your secrets live and inherits that system's rotation, auditing and access control. Broker behaviour is identical either way.

Rotating the data encryption key requires re-sealing

VEEFORE_DATA_ENCRYPTION_KEY seals stored material under the local provider. Changing it without re-sealing makes every credential unreadable at once, and the symptom is every tool failing simultaneously. Plan it as a migration.

Identity, authority, policy and enforcement for autonomous AI agents.