Logs
Every tool call a governed agent makes is recorded: the tool, the decision, the identity behind it, and — for delegated work — the chain it came down. This endpoint reads that trail, so you can reconcile spend, feed a SIEM, or reproduce a governance scorecard from code with no Firebase SDK.
GET https://api.agenticcontrolplane.com/<workspace>/admin/audit
Requires a key with the admin.audit.read scope (or *), or an owner/admin session. The workspace slug in the path must match your key.
Request
curl -s "$ACP/acme/admin/audit?since=2026-06-25T00:00:00Z&limit=200&tool=github.create_issue" \
-H "Authorization: Bearer $ACP_KEY"
| Query param | Type | Default | Description |
|---|---|---|---|
since |
ISO-8601 | 15 minutes ago | Return only entries at or after this time. A bad timestamp returns 400. |
limit |
number | 200 |
Max entries to return. Clamped to 1–1000. |
tool |
string | — | Optional exact tool-name filter. |
Entries come back newest first, ordered by timestamp.
Response
{
"entries": [
{
"id": "evt_9Qd2…",
"tool": "github.create_issue",
"decision": "deny",
"decisionReason": "background tier denied by workspace policy",
"agentName": "Campsite Scout",
"agentTier": "background",
"sub": "apikey:k_7f2a",
"userEmail": "ops@acme.io",
"sessionId": "run_Rk3p_Lm8_04",
"requestId": "req_b81c…",
"ts": "2026-06-25T17:22:09.044Z",
"client": { "name": "Campsite Scout" }
}
],
"count": 1,
"since": "2026-06-25T17:07:09.000Z",
"limit": 200
}
Entry fields
| Field | Description |
|---|---|
id |
Unique entry ID. |
tool |
The tool that was called. |
decision |
allow or deny — what the policy decided. |
decisionReason |
Human-readable reason for the decision. |
agentName |
The agent that made the call. |
agentTier |
interactive · subagent · background · api — how it was running. |
sub |
The identity that made the call (apikey:…, a user UID, or a delegated subject). |
userEmail |
The human behind the call, when known. |
sessionId |
Groups all calls in one run. Join on this to reconstruct a session. |
requestId |
The individual request. |
ts |
ISO-8601 timestamp. |
client |
The connecting client app ({ "name": … }). |
Delegation chain
For calls made by a delegated child key (key delegation), the entry also carries the chain — so a single row reconstructs the full cryptographic ancestry:
| Field | Description |
|---|---|
originSub |
The root identity the chain descends from. |
depth |
How many delegation hops deep this call is. |
chain |
The profile chain. |
runChain |
The run chain. |
parentProfileId |
The immediate parent profile. |
These are absent on non-delegated calls.
Paginating
There’s no cursor — page by time. Read a window, then set the next request’s since just past the oldest ts you received (or pull forward from the newest on a tail). For a continuous feed, poll with since = the last ts you saw.
import os, requests
ACP, slug = "https://api.agenticcontrolplane.com", "acme"
headers = {"Authorization": f"Bearer {os.environ['ACP_KEY']}"}
since = "2026-06-25T00:00:00Z"
while True:
r = requests.get(f"{ACP}/{slug}/admin/audit",
params={"since": since, "limit": 1000}, headers=headers)
entries = r.json()["entries"]
if not entries:
break
handle(entries) # newest-first
since = entries[0]["ts"] # advance past the newest seen
What you can’t do here (yet)
This endpoint returns raw governed events. It does not yet expose the aggregated views the console computes on top of them — per-run cost X-ray (loop vs leaf), per-agent run-to-run variability, or runtime decomposition. Those are on the roadmap as a /api/v1/runs resource; until then, the console is the place to see them, and this endpoint is the raw material to compute your own. See the API overview for where this is headed.