# How to Audit Log Changes with list-audit-events in Agent-Native

> Learn how to audit log changes with list-audit-events in Agent-Native. Query immutable audit records efficiently and effectively with this powerful tool.

- Repository: [Builder.io/agent-native](https://github.com/BuilderIO/agent-native)
- Tags: how-to-guide
- Published: 2026-06-28

---

**The `list-audit-events` action in BuilderIO/agent-native provides a paginated, filterable interface to query immutable audit records stored in the core audit system.**

Agent-Native automatically tracks every state change through its built-in audit infrastructure. The `list-audit-events` action, defined in [`packages/core/src/audit/actions/list-audit-events.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/audit/actions/list-audit-events.ts), exposes these logs for compliance, security monitoring, and debugging. This guide explains how to query audit events from React components and agent scripts using the exact interfaces implemented in the source code.

## Understanding the AuditEvent Schema

When any action modifies state, the audit store in [`packages/core/src/audit/store.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/audit/store.ts) persists an **AuditEvent** record. Each event contains immutable metadata about the change:

- **id**: A unique identifier for the audit entry.
- **resourceId**: The specific ID of the resource that was modified.
- **resourceType**: The logical type of resource, such as `application_state` or `user`.
- **action**: The name of the action that triggered the change (e.g., `create-user`).
- **actorId**: The identifier of the user or agent that performed the operation.
- **payload**: A JSON object containing snapshots of data *before* and *after* the change.
- **createdAt**: The ISO timestamp when the event was recorded.

The audit log is **append-only**; existing events are never modified by write-side code. A background cleanup job defined in [`packages/core/src/audit/cleanup-job.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/audit/cleanup-job.ts) periodically purges events older than the retention period configured in [`packages/core/src/audit/config.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/audit/config.ts).

## The list-audit-events Action Interface

The action follows the standard Agent-Native contract using `defineAction`. It accepts Zod-validated input filters and returns a paginated result set.

**Input parameters** supported by `list-audit-events`:

- `resourceId`: Filter to a specific resource instance.
- `resourceType`: Limit results to a particular resource category.
- `action`: Filter by the action name that caused the change.
- `actorId`: Show only events performed by a specific actor.
- `since` and `until`: Date range boundaries for the query.
- `cursor`: Pagination cursor for fetching subsequent pages.
- `limit`: Number of results per page (default 20, max 100).

**Output schema**:

- `events`: An array of `AuditEvent` objects matching the filters.
- `nextCursor`: A string token for the next page, or `null` if no more results exist.

The handler implementation delegates to `auditStore.listEvents(input)`, which constructs the SQL query and applies field redaction rules based on [`audit/config.ts`](https://github.com/BuilderIO/agent-native/blob/main/audit/config.ts) before returning data.

## Querying Audit Logs from React Components

Use the `useActionQuery` hook to fetch audit data in client-side components. This provides automatic loading states and caching.

```tsx
import { useActionQuery } from "@agent-native/core/client";

export function AuditLogViewer({ resourceId }: { resourceId: string }) {
  const { data, isLoading, error } = useActionQuery("list-audit-events", {
    resourceId,
    limit: 50,
  });

  if (isLoading) return <p>Loading audit history…</p>;
  if (error) return <p>Failed to load audit log.</p>;

  return (
    <ul>
      {data?.events.map((event) => (
        <li key={event.id}>
          {event.createdAt.toLocaleString()} – {event.actorId} performed {event.action}
        </li>
      ))}
    </ul>
  );
}

```

### Implementing Cursor Pagination

For large audit histories, use the `cursor` parameter to paginate through results efficiently:

```tsx
import { useState } from "react";
import { useActionQuery } from "@agent-native/core/client";

function PaginatedAuditLog() {
  const [cursor, setCursor] = useState<string | undefined>(undefined);
  const { data, isFetching } = useActionQuery("list-audit-events", {
    limit: 20,
    cursor,
  });

  const loadMore = () => {
    if (data?.nextCursor) {
      setCursor(data.nextCursor);
    }
  };

  return (
    <>
      <ul>
        {data?.events.map((e) => (
          <li key={e.id}>{e.action} on {e.resourceType}</li>
        ))}
      </ul>
      {data?.nextCursor && (
        <button onClick={loadMore} disabled={isFetching}>
          Load more
        </button>
      )}
    </>
  );
}

```

## Querying Audit Logs from Agent Scripts

Agent scripts can query the audit log programmatically using `runAction`. This is useful for automated compliance checks or generating reports.

```typescript
import { runAction } from "@agent-native/core/agent";

async function showRecentChanges() {
  const oneWeekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
  
  const result = await runAction("list-audit-events", {
    since: oneWeekAgo,
    limit: 10,
  });

  for (const event of result.events) {
    console.log(
      `[${event.createdAt.toISOString()}] ${event.actorId} ${event.action} ${event.resourceType}:${event.resourceId}`
    );
  }
}

showRecentChanges();

```

## Filtering Strategies for Security Audits

Target specific change patterns by combining filters:

**Isolate deletion events:**

```typescript
const { data } = useActionQuery("list-audit-events", {
  action: "delete-user",
  limit: 20,
});

```

**Track changes by a specific actor within a date range:**

```typescript
const { data } = useActionQuery("list-audit-events", {
  actorId: "agent-001",
  since: new Date("2024-01-01"),
  until: new Date("2024-01-31"),
  resourceType: "application_state",
});

```

## Data Redaction and Retention Configuration

Before events reach the action output, the store applies redaction rules defined in [`packages/core/src/audit/config.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/audit/config.ts). This ensures sensitive fields (like passwords or tokens) are stripped from the `payload` even when querying historical data.

The retention policy is enforced by [`packages/core/src/audit/cleanup-job.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/audit/cleanup-job.ts), which runs on a schedule to delete events exceeding the configured age limit. This prevents unbounded storage growth while maintaining compliance windows.

## Summary

- The `list-audit-events` action in [`packages/core/src/audit/actions/list-audit-events.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/audit/actions/list-audit-events.ts) provides the primary interface for reading audit data.
- Events are immutable records stored via [`packages/core/src/audit/store.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/audit/store.ts) and contain full before/after payloads.
- Query filters include `resourceId`, `action`, `actorId`, and date ranges (`since`/`until`).
- Results are paginated using cursor-based navigation via the `cursor` and `nextCursor` fields.
- Sensitive data is automatically redacted according to rules in [`packages/core/src/audit/config.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/audit/config.ts).
- Old events are purged by the cleanup job in [`packages/core/src/audit/cleanup-job.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/audit/cleanup-job.ts) based on retention settings.

## Frequently Asked Questions

### What fields are included in each audit event?

Each `AuditEvent` contains `id`, `resourceId`, `resourceType`, `action`, `actorId`, `payload` (with before/after snapshots), and `createdAt`. The payload provides the complete state change context, while `actorId` identifies who initiated the action.

### How does pagination work with list-audit-events?

The action uses cursor-based pagination. Pass a `limit` to control page size, and use the `cursor` parameter with the value from the previous page's `nextCursor` field. When `nextCursor` returns `null`, you have reached the end of the result set.

### Can I query audit events from the command line?

Yes. Agent-Native exposes actions to the CLI, allowing you to run `agent run list-audit-events --input '{"limit": 10}'` or similar commands depending on your CLI configuration. Programmatic access uses the `runAction` utility in agent scripts as shown in the examples above.

### How long are audit events retained?

Retention is controlled by the configuration in [`packages/core/src/audit/config.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/audit/config.ts) and enforced by the background cleanup job in [`packages/core/src/audit/cleanup-job.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/audit/cleanup-job.ts). Events older than the configured retention period are permanently deleted automatically.