QUICKSTART · 15 MINUTES
Build a governed AI application¶
You are going to build a small AI application against your own API, in your own environment, and finish holding proof of exactly what it did.
Five acts. Get a runtime you control, meet the agent that does the work, hand it a job, point it at an API of yours, then watch the platform refuse something and verify the receipts for the run that worked.
Nothing here is a sandbox or a simulation. Every command below runs real work through the same authorization path a production run uses.
What you'll have at the end
An agent that runs on your machine, a plan that calls an AI model, a second plan that calls a real HTTP API through a credential the agent never sees, a refusal you triggered on purpose, and a signed receipt chain anyone can check.
Before you start¶
You need a terminal on macOS or Linux; Windows works inside WSL. Act 4 calls a real HTTP API, so have an API key ready. The example uses a public weather API, and signing up for a key takes about a minute.
Act 1 · Get a governed runtime¶
About 3 minutes.
Your agents run on your infrastructure. EKKA decides what is allowed to happen and records what did. It never holds your data, your credentials, or your model output. The thing you install below is where the work actually happens, and it is yours.
1 · Install the ekka CLI¶
One signed binary lands on your PATH. That same binary is the CLI you type and the Enclave you start in step 4. Re-running the install line upgrades in place.
2 · Sign in¶
ekka login --email [email protected]
We email you a link. Open it, confirm the code shown in your terminal, and you are signed in. No password to choose and none to lose. If the address is new, signing in creates the account.
3 · Create your organization¶
Pick a code that is yours: lowercase letters, digits and hyphens, starting with a letter, 2 to 63 characters. Codes are unique across all of EKKA, so a common word someone else already took will be refused.
The code you pick is your organization code. Everything you own belongs to it: Enclaves, gates, agents, grants, receipts.
Already invited to someone else's organization? Skip this step. You joined it when you signed in.
4 · Start your Enclave¶
The first start claims the Enclave for this machine and then runs it in the
foreground. Leave it running and open a second terminal for everything
below. Next time, plain ekka enclave start is enough.
On a server, do not leave it in a terminal
That is right for your laptop while you are learning, and wrong for a server: a process in a terminal does not come back after a reboot or a crash. See Running on a server for the five-minute systemd install.
Why the id is safe to share
The id names your Enclave. It does not unlock it. Starting one takes the id and a signed-in person, so someone holding only the id can do nothing with it. That is why an admin can create Enclaves and hand the ids out. The first start binds an Enclave to one machine, and a second machine trying the same id is refused.
The first start looks for Claude Code on this machine
If Claude Code is installed here, that first start records its path and
your Enclave can offer it as a governed model. Nothing runs through it
until you grant a model to a plan. The setting is optional: see
Claude Code on this machine
for the path it writes and how to turn it off.
Check where you stand:
Act 1 done
You have a runtime under your own control. From here on, every command is checked against policy before it does anything, and recorded after.
Act 2 · Meet your agent¶
About 2 minutes.
Before you write anything, meet the thing that will run it.
An agent is the identity your work runs as. It is not a chat wrapper and it is not a prompt. It is a principal your organization owns, and it carries a declaration: the list of capabilities it may ever use. A plan is a job you hand an agent, and the job has to fit inside that list.
5 · See what can act in your organization¶
Your organization already has one. Creating the org created its Core Agent:
AGENT NAME SOURCE PLANS
core-979f755d Core Agent core (yours) 0
what each may touch ekka gate grant list
Look at the PLANS column: zero. The agent exists before any work exists,
which is the shape worth remembering. The agent is the thing that exists and
holds the permissions. A plan is a job you hand it. You never create an agent by
hand; every plan you write belongs to this one unless you install another.
6 · Read what an agent declares¶
This is the part most platforms do not have. One command prints any agent's job description:
Run it now and the declaration is empty, which is correct: an agent that has been asked to do nothing may do nothing. It fills in as you hand it work. After Act 3 the same command prints something like this:
core-979f755d v1.0.0
DECLARED (major 1):
llm.infer [email protected]
The DECLARED block is what the agent asks for, with the plans that use each
item beside it. An agent declares up front, as a list, and a plan that needs
something outside the list is refused when you save it. The declaration is
versioned, and the first number is the permission contract: same major, same
permissions.
Reading it matters most when the agent is not yours. Anything published is in the
catalog, and show works on those too, so you can read a declaration before you
agree to it:
install prints that same declared list and then records that your organization
agreed to that major version. If the publisher later widens what the agent asks
for, they have to bump the major, and nothing crosses a major automatically:
the agent pauses in your organization until one of your admins reviews the new
list and approves it. You are never quietly upgraded into permissions you did not
read.
Act 2 done
You have an employee, and you can read its job description before it does anything. Now give it a job.
Act 3 · Give it a job¶
About 3 minutes.
Your agent needs somewhere for the work to land. See which gates your organization can address:
A gate is how work reaches the outside world: an AI model, a database, an
API, the filesystem. The listing shows each gate's selector, what it can do, and
the model ids or resources it advertises. Note the model id you want from the
llm gate.
7 · Write a plan¶
A plan is one thing your agent knows how to do. You do not start from a blank file:
That writes a complete plan file and prints the exact next commands. The file
carries its own name (ask.v1, taken from the filename) in a plan block at
the top, with the steps beside it, so nothing else is needed to create it. Use
a model id your llm gate actually advertises. If you leave --model off a
gate that offers more than one, the refusal lists the ones you can pick from.
8 · Create it, and watch your agent appear¶
The file is the whole plan, so create takes nothing but the file. (When you
start editing plans, ekka plan validate ask.json runs every check create
would while creating nothing: the same command CI can run.)
✓ Plan created: [email protected]
This plan runs as agent 6e0f42b9-…
That is Act 2 happening. The plan did not create an agent, it joined the Core
Agent you already had; the long id above is that agent's internal id. Commands
address an agent by its code, the first column of ekka agent list, which
is core-979f755d in this walkthrough (yours will differ, and it never changes).
Look at it now, and notice the declaration is no longer empty:
The plan needed llm.infer. Your agent had not declared it, so saving the
plan widened your own agent's declaration and show now lists it with
[email protected] beside it. That is allowed because you own this agent and
have never published it.
It is also exactly why an agent you installed cannot do that. Its declaration is the list your organization read and agreed to, so a plan of the publisher's that needs more is refused instead of quietly growing the list behind you. Same rule, opposite outcome, and the difference is who owns the agent.
9 · Authorize it and run it¶
Declaring is the ask. A grant is the access, and it names which resource. It
also names which gate instance serves it, which ekka gate list printed above
as llm/<instance>:
ekka gate grant add --type llm --instance <instance> \
--resource anthropic/sonnet-4 --capability llm.infer
ekka plan run [email protected] --input user_message="In one sentence, what is a governed run?"
The model call happened from your Enclave. EKKA authorized it and recorded it, and the prompt and the answer stayed with you.
Act 4 · Now bring your own API¶
About 5 minutes.
Here is the part that decides whether EKKA is useful to you. One api gate turns any HTTPS API into something your agents can call and you can govern, so the API does not have to be one anybody integrated for you. The internal service only your company runs works the same way as a public one.
The example below uses a public weather API so it runs for everybody.
Your version of this
Read every apis/weather below as the system you actually care about: your
CI server, your ERP, your helpdesk, your billing service, your internal
reporting API. If it speaks HTTPS and takes a key, this act is unchanged.
Sign up for a key at weatherapi.com, or use a key you already have for an API of your own.
10 · Put the credential in the gate¶
export WEATHER_API_KEY=<your key>
printf '%s' "$WEATHER_API_KEY" | ekka gate credential deposit weather-key --gate api
The secret goes in on stdin, so it never lands in your shell history and never appears on a command line. From here on it is referenced by name.
The credential lives in the gate. Not in the agent, not in the plan, not in the model context. Your agent asks for
apis/weather; the gate is what attaches the key. The agent cannot read it, print it, or leak it, because it never has it.
11 · Point an alias at the API¶
ekka gate alias create apis/weather --gate api --target '{
"base_url": "https://api.weatherapi.com",
"auth_template": { "kind": "api-key-query", "param": "key" },
"credential_ref": "weather-key",
"rules": [{ "method": "GET", "path_prefix": "/v1" }]
}'
That is the whole integration. Four facts:
| Field | What it is |
|---|---|
base_url |
The origin, HTTPS only, no path. Calls can never leave it. |
auth_template |
How the key is attached. bearer, api-key-header, api-key-query, basic, or aws-sigv4. |
credential_ref |
The name you deposited in step 10. Never the key itself. |
rules |
Optional allowlist of method plus path prefix. Leave it out and the whole origin is reachable. |
The label must be two segments, apis/<name>, and the first segment has no
hyphens. Aliases never rebind: to rotate a key, deposit a new ref and create a
new alias.
12 · Write, create, authorize, run¶
plan template prints the exact ekka gate grant add line for your gate, with
the instance already filled in, and plan create prints it again for anything
still missing. Run it, then run the plan:
ekka gate grant add --type api --instance <instance> --resource apis/weather --capability api.read
ekka plan run [email protected] \
--input resource=apis/weather \
--input key="/v1/current.json?q=London"
resource is which alias to call. key is the path and query on that alias.
One plan file serves every path on that API, so you do not write a plan per
endpoint.
Act 4 done
You just built an AI application against your own API, without writing a line of access-control code or a line of audit code.
Act 5 · See the governance¶
About 2 minutes.
Two commands. The first is a refusal you cause deliberately.
13 · Ask for something the agent never declared¶
Your agent declares llm.infer and api.read, because those are what its
plans use. It has never asked to write to your API. Try to grant it that
anyway:
ekka gate grant: This agent does not declare 'api.write', so a grant for it
cannot be issued. If the agent should have it, widen its declaration first
(`ekka agent declare <agent-code> --add api.write`); the grant then names WHICH
resource it may touch.
Read what just happened. The platform said no by name, it named the rule it was enforcing, it named the remedy, and it did all of that before any HTTP request existed. Nothing was tried and then quietly rolled back. Nothing was tried at all.
That is what holds an agent: a declared list, an explicit widen, and a refusal that cites the rule. Not a prompt asking it to behave.
14 · Verify what actually happened¶
It answers with how many records checked out, that nothing has been changed, added or removed since the first one, and how many carry a signature from this machine's Enclave.
Every step that ran is signed, and each signature covers the one before it, so
the entries form a chain. Change any entry and every signature after it stops
matching. verify recomputes the chain and checks the signatures against keys
EKKA publishes openly, which is why it works offline and why someone who does
not trust you can still check it.
To read one run rather than verify the whole chain:
What you actually built¶
Gates are how work flows: a model, an API, a database, a folder. That part is plumbing, and plumbing is not the product.
The product is the other four things. Your agent declares what it wants before it runs. Installing it consents to that exact list, and a change to that list has to come back and ask. Anything outside the list is refused by name, before any I/O, and the refusal is recorded like everything else. And what did happen comes back as a receipt anyone can verify without your login, our help, or your word for it.
That is what makes it rational to hand an AI agent a key to a real system.
What's next¶
Two things turn today's agent into something that works while you are not watching. Both are already in the binary you installed, and the financial analyst clone recipe walks both end to end.
-
Give it a folder you already own
ekka enclave start <id> --data <folder>points your agent at data you already own (a source tree, a documents folder) and it refuses every operation that tries to leave it. Optional, and most Enclaves never need it. The files stay in the clear on your own disk, because you are still using them: EKKA authorizes and receipts every access, and never sees the path or the contents. -
Give it a heartbeat
ekka plan scheduleruns a plan on a cron or a simple interval, for your organization only. Every scheduled run is an ordinary governed run: same grants, same refusals, same receipts. There is no quieter path for timers. -
Stop writing the same steps twice
ekka skill promoteturns an operation you already wrote into a skill: a body of work published under a name, that any plan can call in one step. A published version is never rewritten, so a plan that names@1keeps running what it ran the day you wrote it.
- Build the whole thing → The financial analyst clone
- Wire several steps into one plan → Multi-step plans and schedules
- Publish work once and reuse it → Skills
- Understand the pieces → Core concepts
- Watch one operation in slow motion → How governance works
- Read a real audit chain → Governance receipts
- Every command →
ekkaCLI reference - What's turned on → What's included