Technical architecture
How AgentTrust works under the hood
AgentTrust is a stateless HTTP service with three stages — identity, policy, and audit — sitting in front of a swappable data store. Any agent connects with one request; nothing about your agent's runtime or framework matters.
System overview
Requests flow top-to-bottom: agents authenticate at the edge, pass through the policy engine, and every decision is written to the audit store before the verdict is returned.
Each agent holds an atk_… API key and calls the trust layer over HTTPS before any consequential action.
AgentTrust API · agenttrustcore.com
Request lifecycle
What happens between an agent's intention and a real-world action, step by step.
- 1
Agent
Intercept the action
Right before a side effect (charge a card, write a row, send an email), the agent builds an evaluation request instead of acting directly.
- 2
Agent → API
POST /api/evaluate
The agent sends its Bearer key plus { action, resource, params } over HTTPS. This single call is the entire integration surface.
- 3
API
Authenticate identity
The key is hashed and looked up. Unknown or suspended keys are rejected with 401/403 before any policy runs — fail closed by default.
- 4
API
Evaluate policies
The engine collects every policy whose action glob and resource match, evaluates conditions (e.g. amount > 1000), and resolves the strongest verdict: deny wins over flag wins over allow.
- 5
API → Store
Write the audit record
The request, matched policies, verdict, and reason are appended to the log for accountability — regardless of the outcome.
- 6
API → Agent
Return the verdict
A JSON decision comes back in milliseconds: allow (200), flag (200, proceed with caution), or deny (403). The agent only performs the action on allow/flag.
How another agent connects
Connecting is deliberately minimal — three things, then a single HTTP call before each guarded action.
1. An API key
atk_… key. Store it as AGENT_TRUST_KEYin the agent's environment.2. The base URL
https://agenttrustcore.com. No SDK, VPN, or sidecar is required.3. One call before acting
POST /api/evaluate and act only if the decision is not deny. Works from any language.Minimal client — no dependencies:
// The entire client contract — no SDK required
async function isAllowed(action, params) {
const res = await fetch("https://agenttrustcore.com/api/evaluate", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AGENT_TRUST_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ action, params }),
})
const data = await res.json()
return data.decision !== "deny" // allow + flag proceed, deny blocks
}The API contract
One endpoint, one request shape, four possible outcomes. This is the complete surface an agent needs to understand.
Request
POST https://agenttrustcore.com/api/evaluate
Authorization: Bearer atk_your_agent_key
Content-Type: application/json
{
"action": "payment.send", // required · dotted verb, e.g. email.send
"resource": "stripe", // optional · the system being acted on
"params": { // optional · used by policy conditions
"amount": 5000,
"currency": "usd"
}
}Responses
// 200 OK (allow) // 200 OK (flag)
{ "decision": "allow", { "decision": "flag",
"reason": "No deny policy", "reason": "Matched review rule",
"matchedPolicies": [], "matchedPolicies": ["pol_..."],
"requestId": "req_...", "requestId": "req_...",
"agentId": "agt_..." } "agentId": "agt_..." }
// 403 Forbidden (deny) // 401 Unauthorized (bad/missing key)
{ "decision": "deny", { "error": "invalid_api_key" }
"reason": "Blocked by policy: Block large payments",
"matchedPolicies": ["pol_..."],
"requestId": "req_..." }Design principles
Fail closed
Missing keys, unknown agents, or malformed requests are rejected before any policy runs.
Provider-agnostic
It is plain HTTP + JSON. No framework, language, or runtime assumptions about the calling agent.
Stateless edge
The API holds no per-request state; all durable data lives behind the TrustStore interface.
Storage is swappable
In-memory today for evaluation; implement the same interface against Supabase to make it durable — zero API changes.
Deny beats flag beats allow
When multiple policies match, the strictest verdict always wins, so a single deny rule is enough to block.
Everything is audited
Every evaluation — allowed, flagged, or denied — is recorded with its matched policies and reason.
Where each piece lives
| Layer | File | Responsibility |
|---|---|---|
| HTTP API | app/api/evaluate/route.ts | Auth, orchestration, verdict + status codes |
| Policy engine | lib/trust/engine.ts | Match rules, evaluate conditions, resolve verdict |
| Data store | lib/trust/store.ts | Agents, policies, logs behind one interface |
| Types | lib/trust/types.ts | Shared contracts for agents, policies, decisions |
| Client SDK | sdk/agent-trust.ts | check() + guard() wrapper, zero dependencies |