Skip to main content
An agent reports that a tool call failed. The message it repeats to you came from a model paraphrasing an error, so it is not evidence. Dome recorded the actual decision, and several different gates could have produced it. The skill worth having is narrowing quickly: which gate answered, and what would change the answer.

Hand this to an AI agent. It plants three different failures and walks you through diagnosing each one.

Open in Cursor
In this tutorial, you will plant three failures at three different layers and diagnose each from the outside. By the end you will be able to read an error message and know which command to run first. To do this, you will:
1

Learn the order of the gates

Understand what runs before what.
2

Diagnose a rule denial

Attribute a rejection to the rule that caused it.
3

Diagnose a Gateway access denial

Find the missing Gateway grant that rejects invocation before Cedar evaluates the resource.
4

Diagnose a malformed endpoint

Separate transport problems from authorization problems.
5

Tell denials from redactions

Recognize the events that are not denials.

Prerequisites

For this tutorial, you will need:
  • Govern your first agent completed, with its sandbox still active. You will use its hr-assistant agent, its rule bundle, and its demo-hr connection.
  • The Dome CLI, installed and signed in.
Confirm the workspace, and stay in the sandbox. You are about to break things deliberately:

Learn the order of the gates

A call passes several independent checks before it reaches a backend. They run in a fixed order, and the first one to reject ends the call, so the gate that answered tells you where to look. Two properties of this ladder cause most confusion. Quota sits above rules. A permit that looks correct still fails if the spend cap is exhausted, so a rule you just deployed is not always the thing to change. Discovery behaves differently from invocation. tools/list remains membership- and Cedar-filtered and does not prove that the agent has a Gateway access grant. The grant is enforced when the agent invokes a resource, so use an actual call as the access check.

Diagnose a rule denial

Start with the denial you already have. The hr-assistant rules permit five tools and forbid the rest, so payroll is rejected. Ask the assistant in your MCP client:
Your client shows whatever the model made of the error. The underlying response is a JSON-RPC error with code -32001, carrying dome.authorization_denied in its data.type, and a message that is Dome’s recorded reason rather than the model’s paraphrase. Get the authoritative record:
The access.denied event names the agent, the resource, and the reason. A reason of denied by rule: <id> means an explicit forbid matched. A reason of denied by rule with no identifier, or no rule bundle loaded, means nothing permitted the call rather than something forbidding it, which is a different fix. Confirm the decision without a client in the loop. Simulation runs the same evaluator with no side effects:
Expect DENY with the reason and the determining rule. Add --json for the full response, including the scope trace showing which scope contributed the decision. Then read what the agent is actually running under, which is not always what you think you deployed:
That resolves the whole hierarchy. To see only the agent-scoped bundle, use dome agents get-policies hr-assistant.
Simulation takes the same identity flags the gateway would supply. --actas-sub, --actas-email, --actas-groups, and --actas-roles let you reproduce a denial that only affects one person, and --eval-arguments supplies tool arguments for rules that inspect them.

Diagnose a Gateway access denial

Now revoke the agent’s Gateway grant:
Reload MCP in your client, then ask it to call demo-hr/hr/list_employees. The call fails with agent is not granted access to this gateway before the resource’s Cedar rule is evaluated. Discovery can still list the tool, so a successful tools/list is not an access test. This is the case where simulation misleads you if you ask it the wrong question. Cedar still permits discovery, so a bundle check comes back clean:
That returns ALLOW while invocation is rejected, because Gateway admission runs before resource authorization. The permit is real but is never reached. The command to run first for a missing Gateway grant:
An empty result, or a list without hr-assistant, is your answer. Restore it:
Retry the tool call and confirm it succeeds. The lesson generalizes: when invocation reports a missing Gateway grant, inspect Gateway access before changing resource rules. Membership is the neighboring failure. A tool that exists but belongs to no Gateway is unreachable through that endpoint. This command shows which resources a Gateway actually carries:

Diagnose a malformed endpoint

The third class of failure is not authorization at all, and it is worth being able to rule out in seconds. Call the gateway without naming a Gateway:
You get 400 with select a gateway: use /gateways/{id}/mcp. Nothing was evaluated and nothing appears in audit, because the request never identified a gateway to be evaluated against. The same applies to /v1 for inference. Two related mistakes produce different errors, which is how you tell them apart:
  • A URL missing the /mcp suffix reaches no handler.
  • A valid URL with a wrong or unauthenticated token returns 401 from authentication, ahead of every authorization gate.
The rule of thumb: 400 and 401 are your problem, 403 and -32001 are the policy’s answer. Only the second kind is worth taking to your security team.
Match the message you have to the gate that produced it:
  • select a gateway. The URL omits the /gateways/<id> segment. Nothing was evaluated.
  • 401 invalid or expired token. The credential is wrong, malformed, or rotated. Mint a new key rather than editing rules.
  • 403 agent is suspended or agent is revoked. Lifecycle state, not policy. Check the agent record with dome agents get.
  • act-as header required. The agent requires a verified end-user identity and the call arrived without one.
  • act-as verification failed. An identity was presented but did not verify. Usually a mismatched HMAC secret or an expired token.
  • tool not available in this gateway. Membership. The tool exists but is not in this gateway, or the gateway is inactive.
  • agent is not granted access to this gateway. Admission on invocation. Discovery may still list the resource and is not proof that a grant exists.
  • llm: quota exceeded. A spend cap. The message names the subject that ran out. Check dome model quota list.
  • denied by rule: <id>. An explicit forbid matched. Read it with dome rules show --agent <agent>.
  • no rules for workspace or no rule bundle loaded. Nothing was deployed, so the default deny applied. Deploy a bundle.
  • policy stale or gateway policy stale, fail closed. The gateway’s policy copy aged past its tolerance and it is failing closed. This is an infrastructure signal, not a rule problem.

Tell denials from redactions

Two event types look like failures in a log and are not. A Filter that rewrites a field records mcp.tool_result.filtered, and a Filter that blocks an argument on the way out records mcp.tool_request.filtered. In both cases the call was authorized. Something was changed, not refused. This distinction matters when an agent reports missing data. If the field arrived as [REDACTED], no denial occurred and the rules are not the place to look:
Filters attach to the connection, so every agent reaching that tool inherits them regardless of its own rules. For the full picture of a single request, follow its activity chain. One user action can span many events, and the chain shows them in order:
To read one event in full, including its payload:

Verify the results

Confirm you left the sandbox as you found it. The grant should be back:
The five permitted tools should still allow, and payroll should still deny:
Expect ALLOW then DENY. dome rules simulate exits non-zero on a denial, which makes it usable as a check in CI: assert that the calls you intend to be impossible stay impossible.

Next steps

In this tutorial, you:
  • Learned the order the gates run in, and why quota sits above rules.
  • Attributed a denial to its rule using the audit trail rather than the client’s paraphrase.
  • Found a missing Gateway grant from its explicit invocation denial.
  • Separated transport errors from policy answers.
  • Distinguished a Guard rewriting a field from a rule refusing a call.
Continue with:

Simulate rules

Every flag, including identity and argument evaluation.

Audit reference

Event envelope, filters, chains, and export formats.

Adopt an existing app

Move an app you already run onto the governed path.

Stream Live Events

Live streams, metrics, and OpenTelemetry export.