> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tryhoard.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Reading your agent activity log

> Every preview, every commit, every rejected attempt your AI assistant made, what each row means, what gets redacted, and how to run forensic queries when something looks off.

Every time an AI assistant calls a write action against your Hoard account, it leaves a row in your activity log. Committed changes, rejections, expired plans, floor trips, all of it. This is your audit trail.

This page covers where to find it, how to read a row, and the queries worth running on a quiet Sunday.

## Where it lives

Today the activity log is available through the API at `GET /api/v1/agent/activity` (your assistant calls this for you when you ask "what did you do this week?"). A dedicated Activity tab in Settings → Assistants is on the roadmap.

```
GET /api/v1/agent/activity
```

Authenticate the same way you'd authenticate any other agent call (OAuth or bearer key). The response is a paginated list of activity rows.

You can also ask your assistant directly: "show me everything you've done in the last 24 hours." It will call this endpoint for you and summarize.

## Anatomy of a row

A single row looks like this in the JSON:

```json theme={null}
{
  "id": 12834,
  "action_namespace": "pricing.edit_rule",
  "risk": "low",
  "outcome": "committed",
  "params_summary": {
    "rule_slug": "mythic-standard",
    "before": { "multiplier": 1.10 },
    "after": { "multiplier": 1.15 }
  },
  "floor_violation": null,
  "before_snapshot_id": 4471,
  "after_snapshot_id": 4472,
  "agent_action_plan_id": 9123,
  "request_id": "a1b2c3d4-...",
  "created_at": "2026-05-11T03:42:17Z"
}
```

Read it left to right.

* **action\_namespace**, the binding that was called, namespaced (e.g. `pricing.edit_rule`, `pricing.mass_reprice`, `account.settings`)
* **risk**, `low`, `medium`, `high`, or `critical`
* **outcome**, the verdict (see the table below)
* **params\_summary**, the load-bearing fields of the call. Sensitive values get redacted (see below). The exact keys depend on `action_namespace`.
* **floor\_violation**, name of the hard floor that blocked the call, if any
* **before\_snapshot\_id** / **after\_snapshot\_id**, ids of the rule snapshots taken at preview and commit, for forensic diffing
* **agent\_action\_plan\_id**, links back to the original plan record so you can re-read the diff
* **request\_id**, the request UUID, useful when correlating with server logs
* **created\_at**, ISO-8601 timestamp of when the row was written

## What each outcome means

| Outcome                    | What happened                                                                                                                                             |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `committed`                | The plan was approved (by you or auto) and the change applied.                                                                                            |
| `rejected_by_floor`        | A hard floor tripped. The call never committed. `floor_violation` tells you which one.                                                                    |
| `rejected_by_token`        | The confirmation token was wrong, expired, or already used. Usually means the 60-second window lapsed.                                                    |
| `rejected_by_drift`        | The plan's parameters changed between preview and commit. The assistant tried to commit something different from what you approved. The server caught it. |
| `rejected_by_derivation`   | A computed value on the plan (projected aggregate, affected count) didn't match between preview and commit. Same idea as drift, different field.          |
| `rejected_by_rederivation` | The server re-ran the projection at commit time and got a different number than at preview time, usually because your underlying inventory shifted.       |
| `rejected_by_user`         | You clicked **Reject** on the plan detail page.                                                                                                           |
| `expired`                  | You never confirmed within the 5-minute plan TTL. The plan timed out.                                                                                     |

`committed` is the happy path. Everything else is a story.

## Risk scores: when does each fire

Risk is computed per call against the actual numbers you're sending plus your pricing wizard answers.

* **low**, small move, well under your `change_cap_pct`, affects a modest count of cards, no price-source flip
* **medium**, bigger move, still within caps, or a smaller move on a rule covering many cards
* **high**, exceeds your `change_cap_pct`, or flips `never_go_down`, or changes the price source
* **critical**, would drop your aggregate listed value by a significant percentage, or would push many cards through their floor, or is operating on a rule with very wide reach

The dial that tunes all of this is your pricing wizard. A "Stay Competitive" seller with `change_cap_pct: 20` and a "Win the Buy Box" seller with `change_cap_pct: 30` get different scores for the same call. That's intentional.

## What `params_summary` shows vs what's redacted

Shown:

* Rule names, multipliers, price sources
* Card counts, aggregate dollar projections
* Sale percentages, durations
* Action verbs (edit, create, delete)

Redacted:

* Your bearer key / API key (never logged anywhere)
* OAuth tokens
* Customer email addresses (replaced with anonymized identifiers)
* Free-text fields longer than a threshold (truncated with `...`)

If you ever see a value redacted in a row where you'd genuinely need it, the source of truth is the plan detail page linked from `agent_action_plan_id`. That page shows you everything the assistant saw.

## Forensic queries worth running

A few patterns that come up.

### "Find every rule edit Claude made last week"

Ask your assistant:

> "Show me every committed pricing.edit\_rule action between May 5 and May 11."

Or via the endpoint:

```
GET /api/v1/agent/activity?namespace=pricing.edit_rule&outcome=committed&since=2026-05-05&until=2026-05-11
```

What you're looking for: a steady, sensible cadence. If there's a burst of 20 edits in 4 minutes, something prompt-injected the assistant.

### "Did anyone try to commit a stale plan?"

Filter for `outcome: rejected_by_drift` or `rejected_by_rederivation`. These should be rare. A spike usually means an assistant retried a commit after your inventory shifted (e.g. you ran a sync in between preview and commit). One every couple of weeks is fine; a cluster in one session warrants a look.

### "How many of my confirmations did I actually approve?"

Filter for `action: pricing.edit_rule` over the last 30 days and compare `committed` count to `rejected_by_user` + `expired` counts. If you're rejecting or expiring more than \~20% of confirmations, your grant is probably too loose for what the assistant is suggesting, the assistant should be filtering its own proposals better, but in the meantime, tighten the grant. See [Picking the right permission mode](/tutorials/picking-a-permission-mode).

### "Did anything trip a floor recently?"

Filter for `outcome: rejected_by_floor`. Each row tells you which floor (`absolute_minimum`, `per_rule_aggregate_drop`, `per_session_aggregate_drop`). A floor trip is the system working as designed, the assistant tried something dangerous, the floor said no. But a steady stream of trips means either the assistant is misbehaving or your floors are tuned too tight for how you actually want to operate.

For what to do about each floor type, see [When the agent says 'I can't do that'](/tutorials/when-the-agent-says-no).

## Related reading

* [Agent permissions and safety](/agent-permissions), the three-layer model that produces these rows
* [Your first agent-driven price change](/tutorials/first-agent-price-change), what produces a `committed` row
* [When the agent says 'I can't do that'](/tutorials/when-the-agent-says-no), what produces a `rejected_*` row
* [Going from cautious to confident](/tutorials/trust-progression), using the log as a trust signal over time
