Skip to content

HOW GOVERNANCE WORKS

How governance works

Governance is a Grant, not an if-statement. You never write access-control code. You set a Grant saying which agent may do what, on which resource, and EKKA enforces it the same way over a database, a file, an API and an AI model.

This page is for the engineer who has to explain to somebody else how an AI agent is kept inside its lane.

Nothing is allowed by default. An action with no Grant stops before any I/O, and that refusal is recorded as signed evidence rather than dropped as an error.

Every governed action takes the same four steps, whatever it touches: refused with no Grant, authorized by a Grant you set, allowed through a token issued for that one operation, and returned as a signed receipt you can verify offline.

What are the four moving parts?

The whole model rests on four words. Learn these and you know EKKA.

  • Gate

    A governed boundary over a resource: a database, an AI model, a tool. An agent reaches a resource only through its gate, never around it.

  • Grant

    Durable policy you set once: which agent may do what, on which gate and resource. Nothing is allowed by default. No Grant, no action.

  • Gate Token

    A short-lived, signed permit issued per operation from a Grant. It scopes that one call to exactly what was authorized, then expires.

  • Receipt

    A signed, verifiable record of every access, allowed and denied. Chained so tampering is obvious, and checkable offline without trusting a dashboard.

The one sentence to remember

Governance is a grant, not an if-statement. You set the Grant; EKKA issues the token, enforces the boundary at the gate, and signs the receipt, the same way over your data and over your models.


What happens when an agent acts?

The same four steps, in this order, every time, whether the agent is reading a database or calling a model.

  1. The agent asks. It names an operation on a resource, through a gate. A gate is the only way in; there is no path around it.
  2. EKKA decides first. With no Grant the answer is no, and the refusal is complete: no query is sent, no socket is opened, no credential is read. The refusal is recorded as a signed decision, so "it was blocked" is evidence rather than a claim.
  3. A Grant authorizes it. From that standing Grant, EKKA issues a Gate Token for that one operation. The gate checks the token and returns only what was in scope.
  4. A Receipt is signed. The record is hash-chained, and you verify it on your own machine with no EKKA service in the loop.

Changing what an agent may reach is a change to a Grant, not a deploy. Revoke it and the next attempt is refused a second later.

Where the rules come from

A Grant says what an agent may touch. It is not the top of the chain.

Your Charter is the principles your organization writes down. Policies turn a principle into a rule EKKA checks before a plan runs. Grants say which agent may reach which resource. Receipts are the signed evidence of what actually happened.

Read top to bottom, that answers the question an auditor asks: what did you say you would do, what did you enforce, and what did the machines actually do.


One action, slowed right down

You need the setup from the quickstart

Signed in, an organization, and a running Enclave. If you have not done that yet, start with Build your first agent.

Those four steps on a real gate. You'll use a hosted postgres gate (instance demoV1), a governed boundary over a database, and run one operation on the customers resource.

1 · Try it with no Grant

Ask to list the customers resource before you've authorized anything:

ekka gate postgres list --instance demoV1 --resource customers
BLOCKED  RESOURCE_GRANT_DENIED
This agent holds no Grant for postgres:demoV1/customers.
Refused before any query ran. No data was touched.

What just happened

Nothing is allowed until you grant it. That's default-deny: with no Grant, EKKA refused. The block lands at the policy layer, before any I/O: no query was sent, nothing was read. The refusal is a decision EKKA records, not a silent error.

Preview a decision without running it

Add --check to any gate command to preview allow or deny without executing the operation (no I/O, no cost):

ekka gate postgres list --instance demoV1 --resource customers --check

2 · Authorize it with a standing Grant

ekka gate grant add --type postgres --instance demoV1 --resource customers \
  --capability knowledge.postgres.read
Granted. This agent may now read customers.

A grant may only name a capability the agent already declares

Two different things have to be true, and they happen in this order. The declaration is what the agent asks for. The grant is which resource it may touch. A grant for something the agent never declared is refused:

ekka gate grant: This agent does not declare 'api.write', so a grant for
it cannot be issued.

It works above because creating a plan already widened the declaration for you: while you own an agent and have never published it, ekka plan create adds whatever that plan needs. To widen it yourself, run ekka agent declare <agent-code> --add <capability> first, then grant.

What just happened

A Grant is durable policy you set once: which agent may do what, on which gate and resource. It stays in force until you change it. This is the "grant, not an if-statement" idea: you declared intent, you did not write a check. A read grant covers the list operation you tried above.

The capability is the verb: knowledge.postgres.read says read, and a read Grant covers the list you tried above. There is no separate access level to set, the verb you name is the level. ekka gate list shows what each gate offers.

You didn't name an agent: ekka resolves your agent for you, so you never paste a UUID. On a team with more than one agent, add --agent <id> to grant to a specific one.

3 · Run the same operation again

Nothing about the command changes. Only the policy did:

ekka gate postgres list --instance demoV1 --resource customers
ALLOWED  the gate returned only what's in scope.

What just happened

Because a Grant now covers it, EKKA issued a short-lived, signed Gate Token from your Grant just for this operation. The gate verified that token and returned only what was in scope. Anything outside the token's scope is never handed back.

Under the hood: Grant vs Gate Token

The Grant is the durable policy (it lives until you revoke it). The Gate Token is issued fresh, per operation, and expires almost immediately. So the standing permission and the thing sent over the wire are two different objects: revoke the Grant and no new tokens can be issued, while any token already issued was only ever good for one scoped call.

4 · See the signed record

Every access, allowed and denied, is a signed Receipt. Look at the one you just created (use the run id printed by the previous command):

ekka receipts show <run-id>
ekka receipts verify

receipts show prints the signed record of the one run you name. receipts verify takes no run id: it checks the whole local chain, and answers with how many records checked out and that nothing has been changed, added or removed since the first one.

What just happened

receipts show prints the signed record of exactly what happened; receipts verify re-checks the hash chain and every signature yourself, offline, without trusting any dashboard. That is the difference between claiming your AI was governed and being able to prove it.

5 · Governance is a live dial

Revoke the Grant, and the very same operation is blocked again. Re-grant, and it flows again, enforced instantly, with no code change:

ekka gate grant revoke <grant-id>
# ekka gate postgres list ... -> BLOCKED again
# ekka gate grant add ...     -> ALLOWED again

What just happened

You changed what your agent can reach by changing a Grant, not by editing and redeploying code. That is the whole product in one move: governance is a grant, not an if-statement.



Does an AI model work the same way?

An AI-model call is a governed operation too. The AI-model gate (type llm) is just another gate, with the same grammar you just used on the database: deny, grant, allow, receipt.

The shape is identical. You ask for a model completion:

ekka gate llm infer --instance ekka.ai_gateway --resource anthropic/sonnet-4 --input '{"prompt":"..."}'

With no Grant, it's blocked before the model is ever called. You authorize it with a Grant exactly like the database:

ekka gate grant add --type llm --instance ekka.ai_gateway --resource anthropic/sonnet-4 \
  --capability llm.infer

Then the same call is allowed, and the model's answer comes back as a signed receipt you can verify.

What just happened

A database and an AI model are governed the exact same way: deny, grant, allow, receipt. One governance model, every gate. Nothing reaches a model without a Grant, and the model's answer is itself a receipt you can verify.


Who says yes when work is shared?

Running work is governed above. Sharing work is governed the same way: with a request a person answers, never a landing.

A plan or a skill you create is yours alone. publish offers it, one rung at a time: an administrator accepts it into your organization with approve or turns it down with decline --reason, and moving from the organization to the public catalog is a second request that EKKA answers. The queue is a filter, not a dashboard:

ekka plan list --requested
ekka skill list --requested

Nothing reaches your organization, or ours, without a named person saying yes, and the receipt shows who. An administrator offering their own work still asks and then accepts, as two recorded acts, so the chain shows the same person on both sides instead of one word hiding two decisions.

An agent and a connected API start one rung higher, at the organization, and they have no rung below it. An agent is a who, not a body of work: your own plans run as it from the moment it exists, so there is no state in which it belongs to one person. A connected API already belongs to the organization that connected it. For both, the request that needs answering is the step out to every organization on this EKKA, and EKKA answers that one.