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.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.
Where it lives
Today the activity log is available through the API atGET /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.
Anatomy of a row
A single row looks like this in the JSON:- action_namespace, the binding that was called, namespaced (e.g.
pricing.edit_rule,pricing.mass_reprice,account.settings) - risk,
low,medium,high, orcritical - 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 flipsnever_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
change_cap_pct: 20 and a “Lead the Market” 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)
- 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
...)
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:
”Did anyone try to commit a stale plan?”
Filter foroutcome: 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 foraction: 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.
”Did anything trip a floor recently?”
Filter foroutcome: 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’.
Related reading
- Agent permissions and safety, the three-layer model that produces these rows
- Your first agent-driven price change, what produces a
committedrow - When the agent says ‘I can’t do that’, what produces a
rejected_*row - Going from cautious to confident, using the log as a trust signal over time