Agent Integration: Scoped axn_* Tokens and Least-Privilege Practice
Let AI agents manage your resources safely: scoped tokens issued per task whitelist, credentials only via environment injection, tool surfaces with stated bla
# Treat your agent like a brilliant intern: scope everything
An AI agent is the new ops intern: capable, tireless, and entitled to exactly as much permission as an intern — which is to say, almost none at first. This guide covers scoped tokens, credential injection, tool-surface design and the audit loop: five steps, each verifiable. The interface overview lives in the API reference; this piece is the security discipline around it.
## Step 1 — Scoped tokens: least privilege as practice, not slogan
The admin API accepts three key classes (master key, console session, scoped token). **Agents get only the third: `axn_*` scoped tokens**, authorized per scope vocabulary (articles / markets / courses / settings / tokens / ops / ugc …), revocable individually without collateral damage. Three issuance rules:
- **One agent, one key.** Shared tokens destroy auditability and couple revocations.
- **Scope = task whitelist.** A content assistant gets `articles`; a markets bot gets `markets`. "Just give it everything for now" is the down payment on an incident.
- **Lifecycle is owned.** Tokens live in a ledger (who, which scope, issued when, rotated when); 90-day rotation is a sane default.
```bash
# issue an articles-scope token with the master key (env-injected, never in shell history)
curl -s -X POST "$PORTAL/api/admin/tokens" \
-H "Authorization: Bearer $AX_MASTER" -H "Content-Type: application/json" \
-d '{"name":"content-agent","scopes":"articles"}'
# the plaintext token appears ONCE -> write it straight into the agent's secret store
# verify the boundary (articles token touching settings must 403):
curl -s -o /dev/null -w "%{http_code}\n" -H "Authorization: Bearer $AXN_CONTENT" "$PORTAL/api/admin/settings" # expect 403
```
## Step 2 — Credential injection: how the agent holds keys
- **Environment or platform secret store only.** The token enters the process at runtime; it never enters the repo, the logs, or the prompt. For agents these three red lines matter more than for humans: agent conversations and tool logs are retained systematically.
- **Prompts carry references, never values.** The system prompt says "use the token in environment variable AXN_CONTENT" — not the token. That is the first wall against prompt injection: if the agent is tricked into emitting its context, the value isn't in the context.
- **Suspect ⇒ rotate.** Token appeared in a log, agent behaved oddly, a third-party tool touched the environment — revoke and reissue. Cost: five minutes. Cost of not doing it: unbounded.
## Step 3 — Tool-surface design: make every action predictable
When wrapping the API as agent tools (function-calling / MCP descriptions), four design points:
- **State the blast radius in the description.** "This tool publishes content to production" — the model's planner must feel the weight.
- **Confirmation layer for writes.** Publish/delete tools go two-stage (draft first, publish second) or take an explicit human-confirm parameter. This portal's R5 discipline (AI content always lands as draft awaiting human approval) is that layer institutionalized.
- **Pass the error contract through.** Return the `{error, code, requestId}` envelope verbatim to the model: codes are machine-readable, so the model branches correctly between 40xxx (fix parameters, retry) and 403xx (permission denied, do NOT retry).
- **Rate awareness in the description.** Writes ~60 req/min class, batch spacing ≥2 s — the agent's plan then throttles itself.
## Step 4 — Audit loop: every action replayable
All admin writes land in the audit log (actor / IP / action / object). Post-integration cadence: **daily** scan for anomalous actions (writes outside work hours, burst failures); **weekly** reconcile the ledger (token usage vs expected tasks); **monthly** rotate. Keep agent-side records too (which model, which input, which call, which return) so incident retrospection runs in both directions. Minimum retention: 90 days, matching this portal's own audit retention. Three anomalies demand immediate action: privilege attempts (scope design has holes), burst failures (tool description or parameter mapping is wrong), activity outside task windows (token may have leaked — rotate now).
## Step 5 — Worked example: content-assistant permission design
| Task | Tool | Scope | Guardrail |
|---|---|---|---|
| Draft article | POST articles (status=draft) | articles | drafts only; publish is human |
| Health-check words/images/tables | GET admin articles (stats) | articles | read-only |
| Revise content | PUT articles/{slug} | articles | published items frozen (back to draft first) |
| Market data entry | POST markets (null semantics) | markets | no measured data ⇒ must stay null |
| Publish | — (not granted) | — | the human keeps the last step |
That table IS least privilege made concrete: **the agent gets exactly enough to do the job; the publish right stays human.** This portal's own content pipeline runs on it — every draft awaiting approval in this column is live evidence.
## Acceptance checklist (run all five after integration)
```bash
# 1 scope enforcement: cross-scope access -> 403
curl -s -o /dev/null -w "%{http_code}\n" -H "Authorization: Bearer $AXN_CONTENT" "$PORTAL/api/admin/settings"
# 2 error contract: bad params -> 40xxx envelope with requestId
curl -s -X POST "$PORTAL/api/admin/articles" -H "Authorization: Bearer $AXN_CONTENT" -H "Content-Type: application/json" -d '{"slug":"x"}'
# 3 rate limits: burst writes -> observe 429 and back off
for i in 1 2 3; do curl -s -o /dev/null -w "%{http_code} " -X POST "$PORTAL/api/admin/articles" -H "Authorization: Bearer $AXN_CONTENT" -d '{}'; done; echo
# 4 audit: every agent write visible with matching actor and IP
curl -s -H "Authorization: Bearer $AX_MASTER" "$PORTAL/api/admin/audit?limit=5"
# 5 revocation: revoke in console -> expect 401; the agent must REPORT, not fail silently
curl -s -o /dev/null -w "%{http_code}\n" -H "Authorization: Bearer $AXN_OLD_REVOKED" "$PORTAL/api/admin/articles?limit=1"
```
Related: API reference · Webhooks & events · SDKs & libraries. The full agent attack surface (prompt injection, credentials, least privilege) is covered in the AI & agent security batch; trend context in the future-web series.