Skip to main content

Format

The event log is NDJSON, one JSON object per line, emitted in chronological order. Every object has an "event" field identifying its type and a "ts" field with a Unix timestamp in milliseconds.

Output destination

By default, events are written to stdout, interleaved with your agent’s own output. To separate them, configure file output:
This writes to .nanny/logs/log.ndjson, a location Nanny always owns and auto-creates, never something you point at a path yourself. Only set file if you want a different name: a bare name, no extension. Nanny always appends .ndjson itself:
.nanny/logs/ is meant to stay out of git (Nanny adds it to .gitignore automatically the first time it’s created): it’s a local audit trail, not source. If you later log this NANNY_API_KEY, Cloud sync can back-fill from whatever accumulated in that folder before sync was ever turned on, not just events going forward. Or pipe stdout to a file at the shell level:

Guaranteed events

Every execution emits exactly these two events, in this order:

ExecutionStarted

Always the first event. Emitted immediately before the child process is spawned.

ExecutionStopped

Always the last event of a complete run. Emitted on every exit path: clean exit, a policy stop, an error, or a signal.
If this event is missing from a run, the process crashed. That absence is itself a fact worth reading. reason is one of four: ToolDenied, RuleDenied, AgentCompleted, or ManualStop. Only the first two are policy violations.

SDK events

When the Rust SDK macros or Python SDK decorators are active, additional events are emitted for each tool call. These appear between ExecutionStarted and ExecutionStopped: ToolDenied and RuleDenied are distinct denial events. ToolDenied means the tool was not permitted at all; RuleDenied means the tool was permitted but a rule blocked this specific call. ToolFailed is different from both: the tool was allowed and called, but hit a runtime error. No tokens are recorded for a failure.

Using the log

The event log is designed to be piped into standard tools: