Request path
One protected action, traced from the agent's process to your downstream and back.
The same journey as How it works, from the process and network point of view.
#1. The agent signs
In the agent's process. The private key never leaves it.
tsconst assertion = createAssertion({
agentId, keyId, privateKey,
audience: 'https://gateway.veefore.example.com',
purpose: 'agent_authentication',
});
Ed25519 over base64url(header) + "." + base64url(canonicalJson(payload)), with
a fresh nonce and a two-minute expiry.
#2. Token exchange
httpPOST /gateway/v1/token
The gateway verifies the signature against the stored public key, checks the audience string, the timestamp window, the nonce, the key generation and the revocation state. Then it issues a session token with a 15-minute lifetime.
No refresh token. The agent re-signs when the token expires, because the key is a strictly better credential than a refresh token would be.
#3. The protected action
httpPOST /gateway/v1/actions
authorization: Bearer aos_at_…
idempotency-key: refund-ord_8812
This is where the twelve stages run. Each stage is cheaper than the one after it and narrows what the next has to consider.
text 1 REQUEST schema, timestamp, nonce
2 AUTHENTICATION session token → agent identity
3 IDENTITY generation current, not revoked
4 LIFECYCLE agent ACTIVE, not isolated, environment not paused
5 CAPABILITY capability held, tool enabled and authorized, destination allowed
6 DELEGATION chain resolves; intersect every hop; compare the request
7 POLICY every in-scope policy, every rule; strictest decision wins
8 RISK thirteen signals, weighted; policy already read these
9 APPROVAL create, or validate a presented one
10 CREDENTIAL ── first side effect outside Veefore ──
11 EXECUTION real HTTP, six egress guards
12 RESULT apply limits and masking, seal the record
Stages 1–9 can all refuse, and none of them has an external effect
Which is what makes stage 10 the first irreversible step. A blocked action never causes a credential to be issued, so "we blocked it" and "the secret did not go out" are the same statement rather than two.
#Database reads during the pipeline
Stages 3 through 9 read from PostgreSQL: the identity and its generation, the agent and environment state, capability grants and tool authorizations, the delegation chain, the active policy versions bound to the scope, velocity and history counters, trust evidence, and any presented approval.
No decision is cached. Every action re-resolves live state. That is why revocation is instant: there is no cached grant to expire.
#4. The credential lease
Stage 10. The broker unseals the material with
VEEFORE_DATA_ENCRYPTION_KEY, issues a lease scoped to this action with a
600-second default lifetime, and records it by reference.
The lease goes to the tool runtime, inside the gateway process. The agent never receives it and has no way to ask for it.
#5. Egress
Stage 11. Six guards, in order:
| Refusal | |
|---|---|
Tool kind is HTTP |
Otherwise the simulated runtime runs |
endpoint_url is set |
UNPROCESSABLE |
Host is in this tool's own destination_allowlist |
DESTINATION_BLOCKED |
| HTTPS, unless the host is loopback | DESTINATION_BLOCKED |
redirect: 'error' |
Execution fails |
| Timeout at 15s | EXECUTION_TIMEOUT |
Plus a per-tool circuit breaker: five consecutive failures opens it for 20 seconds.
The destination allowlist is checked twice — once in stage 5, once here. The second check protects you if the endpoint was edited after the first, and if a code path ever reaches execution without stage 5 having run.
Headers sent:
httpcontent-type: application/json
accept: application/json
user-agent: Veefore-Gateway/1.0
x-veefore-request-id: req_01JAV…
x-veefore-agent-id: agt_01JAV…
idempotency-key: refund-ord_8812
traceparent: 00-4bf92f35…-00f067aa…-01
Plus whatever the leased credential contributes. x-veefore-request-id is worth
logging on your side — it ties your downstream log line to the Veefore action
record.
#6. Result
Stage 12. LIMIT caps are applied, MASK paths are redacted from the response
before the agent sees them and from the audit record, the stage results are
assembled, and the action record is sealed.
The audit event is hash-chained into the trail.
#7. The response
json{
"actionId": "act_01JAV…",
"requestId": "req_01JAV…",
"traceId": "4bf92f35…",
"mode": "ENFORCE",
"decision": "ALLOW",
"outcome": "ALLOWED",
"allowed": true,
"result": { "refundId": "rfnd_0005", "status": "accepted" },
"reason": "Within the refund policy baseline.",
"explanation": { … },
"latencyMs": 84,
"stages": [ … ]
}
#Network boundaries
textagent host gateway host downstream host
────────── ──────────── ───────────────
private key ──TLS──▶ pipeline ──TLS──▶ real effect
no credential credential
broker
│
▼
Postgres (private)
▲
│
browser, CLI ──TLS──▶ control plane
Separate ingresses
The gateway exposes only /gateway/v1/* and
/.well-known/veefore-platform-key. The control plane exposes only /v1/*,
and is not reachable from wherever agents run.
That separation is the control that makes the plane split worth having. → Deployment
#Latency
| Typical | |
|---|---|
| Signature verification | 1–3 ms |
| Policy evaluation | under 1 ms, in-process |
| The full pipeline, excluding execution | 20–50 ms |
| Execution | your downstream |
Policy evaluation being in-process is a deliberate requirement, not an optimisation: the gateway cannot take a network hop to another service that could be down in order to decide whether to allow something. → Policy engine
veefore_gateway_request_duration_ms is labelled by outcome, and the trace
has one span per stage — so "why was that slow" is answered by looking at which
stage holds the time. Usually EXECUTION, which means your downstream.
#What changes by mode
OBSERVE |
SIMULATE |
ENFORCE |
|
|---|---|---|---|
| Stages 1–9 | run | run | run |
| A refusal stops the action | no | yes | yes |
| Stage 10 credential | leased | skipped | leased if allowed |
| Stage 11 execution | runs | skipped | runs if allowed |
| Stage 12 record | written | written | written |
OBSERVE runs the whole pipeline, records the refusal in shadow, and then
lets the action proceed. → Enforcement modes