Your first authorized
call in 10 minutes.
Connect an agent. Create an app. Attach a policy. Trigger a call. Every step shows the exact command for the path that fits how you work — CLI, MCP, TypeScript SDK, or Python SDK. Pick once; it sticks across steps.
Connect an agent.
Every agent identifies itself to Nomos with an API key. CLI users export it once. MCP clients put it in their config. SDK users pass it to createIntentClient(). The key says who is asking — policy still decides every call.
- · Issued from /app/api-keys
- · Visible exactly once
- · Revocable per-key, per-app
import { createIntentClient } from '@auto-nomos/sdk';
const client = createIntentClient({
controlPlaneUrl: process.env.NOMOS_CONTROL_URL!,
apiKey: process.env.NOMOS_API_KEY!,
});Create an App.
An App is one agent's identity inside your org. It carries a DID for signing UCANs, a default policy, and its own API keys. The name shows up in every audit row forever — name it accurately.
- · One DID per agent
- · Mode: dynamic or static
- · Rotate keys without breaking the App
const app = await client.apps.create({
name: 'Inbox triage bot',
mode: 'dynamic',
});
const key = await client.apps.keys.create({
appId: app.id,
});
// store key.value — only returned onceAttach a policy.
Without a policy, every authorize denies — fail-closed by design. The fastest path: the starter template github:read-only. Edit it later or build your own in the visual policy builder.
permit (
principal,
action == Action::"github:issue:list",
resource is GithubRepo
)
when { principal.app == resource.allowed_app };const policy = await client.policies
.createFromTemplate({
template: 'github:read-only',
name: 'GitHub read',
});
await client.apps.attachPolicy({
appId: app.id,
policyId: policy.id,
});Trigger your first call.
Authorize gives you a UCAN. Hand that UCAN to the PDP and it makes the real GitHub call on your behalf. Your agent never holds the OAuth token — every step lands in the audit chain.
- 14:22:11allow/github/issue/list (proxy)ae71…1c7b
- 14:22:10allow/github/issue/list (authorize)1c7b…09f4
- 14:22:09initapp.created · Inbox triage bot09f4…0000
prevHash. Daily roots are Ed25519-signed and replayable via @auto-nomos/audit-verify.const grant = await client.authorize({
command: '/github/issue/list',
resource: { provider: 'github', owner: 'acme', repo: 'app' },
ttlSeconds: 300,
});
if (grant.decision !== 'allow') {
throw new Error(grant.reason);
}
const issues = await fetch(
`${process.env.NOMOS_PDP_URL}/github/issue/list` +
`?owner=acme&repo=app`,
{ headers: { authorization: `Bearer ${grant.ucan}` } },
).then((r) => r.json());Ship the agent.
Watch every call.
Same flow for every integration in the catalog — Slack, Stripe, Notion, Google, AWS, Azure, GCP, filesystem, SSH, Postgres, and twenty more.