---
title: FAQ
description: The questions that come up repeatedly, answered without hedging.
---

## Does the SDK enforce anything?

No. The gateway does. The SDK formats and signs requests and gives you typed
errors; every decision is computed server-side on every call.

The test of whether a security layer is real is what happens when you remove it.
Remove the Veefore SDK and your agent has no credential to call your tool with,
because the credential lives in the broker and is released only after an action
is permitted. See [The boundary](/secure/boundary).

## Can an agent bypass Veefore by calling our API directly?

Only if your API accepts unauthenticated calls, which is a problem you had
already. The intended shape is that your tool's credential exists **only** in
the credential broker — not in the agent's environment, not in its config, not
in a vault the agent can read. Then "calling directly" means calling with no
credential.

If an agent currently holds a long-lived key for your API, move it into the
broker. That migration is the single highest-value thing you can do.

## What happens if Veefore is down?

Protected actions are refused. Not allowed — refused, with a specific `503`:
`POLICY_SERVICE_UNAVAILABLE`, `IDENTITY_SERVICE_UNAVAILABLE`,
`CREDENTIAL_SERVICE_UNAVAILABLE` and so on.

This is deliberate and it is tested in the chaos suite. An authorization system
that allows everything when it cannot evaluate is worse than no authorization
system, because you believe you have one. See
[Fail closed](/secure/fail-closed).

Plan for it the way you plan for any critical dependency: run more than one
instance, monitor `/health/ready`, and know which agents stop working.

## Why does OBSERVE let blocked actions through?

Because OBSERVE's job is to tell you what enforcement would do without changing
what currently happens. If it refused things, adding Veefore to a running system
would break it on day one, and nobody would adopt it.

The cost is that OBSERVE provides no protection. `decision` is the effective
outcome and `shadow.decision` is what enforcement would have done; when they
disagree, the action still happened. Treat OBSERVE as instrumentation and leave
it quickly. See [Enforcement modes](/concepts/enforcement-modes).

## Why is a `BLOCK` from a low-priority rule beating my high-priority `ALLOW`?

Because strictness wins, not priority:

```text
BLOCK > REQUIRE_APPROVAL > STEP_UP_AUTH > LIMIT > MASK > ALLOW
```

Priority orders evaluation and the explanation. It does not override strictness.
This is what stops you accidentally un-blocking something by adding a
high-priority allow rule.

If you need to carve out an exception, narrow the `BLOCK` rule's condition. Do
not try to out-rank it. See
[Policy precedence](/concepts/policy#precedence-the-part-to-read-twice).

## Everything is suddenly blocked and no rule looks relevant

Check for a deny-by-default policy bound to a broad scope. A policy with
`"defaultDecision": "BLOCK"` bound at `ENVIRONMENT` level denies **everything**
in that environment, because every other policy's `ALLOW` loses to it.

```bash
veefore policies list
```

Look for a policy whose scope is wider than its purpose. A database guardrail
belongs on the agent or the tool it constrains, not on the environment. See
[Tenancy](/concepts/tenancy).

## I get a bare 401 from the gateway and the key is correct

Almost certainly the audience. The gateway compares the `aud` in your assertion
against its configured public URL **as a string**, so
`http://127.0.0.1:4010` and `http://localhost:4010` are different values for the
same host.

```bash
curl -s https://gateway.veefore.example.com/.well-known/veefore-platform-key
```

Use the `audience` from that response. `veefore init` fetches it rather than
assuming. See [Agent identity](/concepts/identity).

## What is the difference between a capability and a tool?

A capability is an abstract permission the agent holds (`refund.create`). A tool
is a concrete registered endpoint that *requires* a capability.

Both must line up: the agent needs the capability **and** must be explicitly
authorized for that specific tool. Registering a tool grants nobody anything —
otherwise adding a tool would silently widen every existing agent's reach. See
[Capabilities](/concepts/capabilities).

## Why was my delegation refused instead of just capped?

Because silent clamping means the caller believes it has authority it does not
have, and finds out at the worst possible time. A delegation asking for more
than its parent holds is refused with `DELEGATION_ESCALATION` at creation time.

Note that narrowing anywhere in a chain narrows everything below it. If an
intermediate hop capped the amount at ₹50,000, the leaf's ceiling is ₹50,000
even if the leaf's own grant says more. `GET /v1/agents/{id}/authority` shows the
resolved result.

## Veefore allowed the action but the downstream returned 401

Veefore permitted it and brokered a credential; the downstream rejected what it
received. The usual cause is credential material stored under a key the broker
does not read for that credential type — `API_KEY` reads `api_key`, `apiKey`,
`key` or `value`, and discards anything else.

This used to fail silently two layers from its cause. It is now refused at
registration and rotation with `INVALID_CREDENTIAL_REFERENCE`. See
[Broker a credential](/build/broker-a-credential).

## Can I use my own policy engine?

You can export to Rego and run OPA alongside, and the semantics are equivalent.
The TypeScript IR remains authoritative inside Veefore, because the gateway
needs evaluation to be in-process, deterministic, total and sub-millisecond
without a network hop to another service that could be down. The reasoning is in
[Policy engine](/architecture/adr/0003-policy-engine).

## Does Veefore hold money, or process payments?

No. Not a wallet, not a processor, not a ledger, not a settlement system.
`amount` exists purely as a policy input and as recorded decision context.

This is enforced, not just stated: `npm run scope:audit` fails the build if a
balance column, a payments route or a settlement table appears anywhere. See
[What Veefore is not](/scope).

## Then why can a policy test an amount?

Because "refunds above ₹1,000 need a human" requires a number. Veefore reads
the number, decides, records what it decided, and moves nothing. The money moves
in your system, through your tool, with a credential Veefore brokered after
permitting the action.

## Can I revoke a revocation?

No. `REVOKED` is terminal. Register a new agent.

Inconvenient, and much less inconvenient than a revocation that can be undone by
whoever caused the incident. If you want a reversible stop, use `pause`
(operational) or `suspend` (security).

## What is the quickest way to protect an existing agent?

```bash
npm install -g veefore
cd your-agent-project
veefore
```

It signs you in through the browser, finds the framework and tools, registers
them after you confirm, and wraps each tool in `guard()` with a diff, a backup
and automatic rollback. See [Automatic setup](/build/automatic-setup).

## Why does `veefore login` open a browser?

So your password, MFA and SSO happen in the console and never in a terminal.
The CLI only receives a session token, which you can revoke from your profile.
Over SSH, or with `veefore login --device`, it shows a link and a code to enter
in any browser instead. See [Authentication](/reference/authentication#cli).

## How do I run the CLI in CI, with no terminal?

Nobody can open a browser in CI, so prompts fall back to defaults when stdin is
not a TTY, and the secret prompt refuses outright. Supply credentials as
environment variables:

```bash
VEEFORE_EMAIL=ci@example.com \
VEEFORE_PASSWORD=… \
VEEFORE_MFA_CODE=… \
veefore test
```

See [Gate your pipeline](/build/ci-gate).

## Why is my agent tripping risk signals on everything?

Several signals are baseline signals — they compare against what *this agent*
has done before. A brand-new agent has no baseline, so `NEW_TOOL`,
`NEW_RESOURCE` and `UNUSUAL_DESTINATION` fire on nearly everything.

That is correct. Run new agents in `OBSERVE` or `SIMULATE` long enough to
establish a baseline before promoting.

## Does the audit chain prove nobody tampered with it?

It proves the stored sequence has not been altered since it was written, and it
localises any break to a specific position. It does not prove completeness
against an attacker with database write access *and* the chain secret, who could
rewrite the chain consistently.

Keep the chain secret out of the database, restrict write access, and ship
events to an append-only sink. The chain's job is to make quiet, surgical
tampering impossible. See [Audit integrity](/secure/audit-integrity).

## Where do I report a security issue?

[Responsible disclosure](/secure/disclosure).
