AuditService.logEvent(). Mutating actions also capture a before-state snapshot for 7 days, after which the snapshot is purged (the audit entry stays forever).
What is audit-logged
NewAuditAction values added by the agents feature:
| Action | Fires when |
|---|---|
AGENT_CREATED, AGENT_UPDATED, AGENT_ACTIVATED, AGENT_PAUSED, AGENT_RESUMED, AGENT_DELETED | Lifecycle. |
AGENT_RULE_SET_CREATED | A new rule-set version is saved. |
AGENT_CYCLE_COMPLETED | One agent cycle finishes (summary in payload). |
AGENT_AUTO_ACTION | One autonomous mutating tool call (tool name + target id in payload). |
AGENT_UNDO_APPLIED | Someone clicked Undo in the workspace Undo Center. |
AGENT_PENDING_RESOLVED | A pending item moved from OPEN to RESOLVED / DISMISSED. |
AGENT_DATA_SOURCE_PULL, AGENT_RESULTS_PUSHED | Inbound / outbound sync activity. |
actor.type=agent.
The 7-day undo window
Mutating tool calls populateagent_undo_snapshot.before_state_json before dispatch via a Snapshottable interface implemented per affected service. The snapshot includes everything needed to restore: the entity’s full state at the time of the change, with a currentAfter field captured at undo time for drift detection.
What’s undoable
| Action | Undoable? | Note |
|---|---|---|
| Mismatch report state transitions | Yes | Reverts to the prior state (typically OPEN). |
| Mapping mode preference changes | Yes | Restores the previous mode. |
| Pending item creations | Yes (via dismiss) | Dismissing a pending item is equivalent to undo for human-facing escalations. |
| Memory notes | No | Manage via the Memory tab — delete notes directly. |
| Notifications sent (email / Slack / webhook) | No | Cannot un-send. |
External webhook calls (push_results_to_sink) | No | Egress side effect. |
trigger_mapping_job | No | The job runs. Future cycles can be cancelled instead. |
remember() writes | No | Same as memory notes — manage directly. |
Using the Undo Center
/workspace/agent-undo (UI) or GET /api/v1/workspaces/{wid}/agent-undo (API). The table sorts by expires_at asc so soonest-to-expire is on top.
Click Undo
The runtime captures the current state, compares it to the snapshot, and applies the before-state.
Drift-conflict modal
Whencurrent ≠ after, the runtime returns MERGE_CONFLICT (HTTP 409) from the undo endpoint. The UI surfaces:
- Snapshot’s before state
- Snapshot’s recorded after state
- Current actual state
- A two-button choice: Proceed anyway (apply before-state, drop intermediate change) or Cancel.
AGENT_UNDO_APPLIED audit entry with the mergeConflict=true flag.
Authorization
| Role | Can undo? |
|---|---|
OWNER, ADMIN | Yes. |
MEMBER | No — read-only on the undo center. |
Snapshot retention
AgentUndoSnapshotPurger runs daily and drops snapshots where expires_at < now(). The corresponding audit entries remain — only the snapshot payload is purged.
API
POST .../undo:
200— applied cleanly.409—MERGE_CONFLICT(use?force=trueto override).410— snapshot expired (>7 days old).404— snapshot not found / already undone.
Related
- Agents overview — 7-day undo is part of trust by design.
- Rules and decisions — rule-set versions are audit-logged here.