Agent Session Audit Log — Operations Guide
Table:
dev_r_agent_sessionsin Supabase projectmwkqmgadqnkkihjdeqsiMigration:monitoring/supabase/migrations/20260618170113_723_agent_sessions.sql
What it tracks
Every Claude Code session that runs in the p24-infra ecosystem writes a row to
dev_r_agent_sessions. This gives a complete audit trail: which worker ran,
when, what skill was invoked, which issues were touched, and how sessions relate
to each other in a parent → subagent hierarchy.
Type hierarchy
type | parent_session_id | Description |
|---|---|---|
worker | NULL | Top-level session: hourly triage, issues-review, manual dev work |
subagent | parent’s session_id | Spawned via the Agent tool by a worker session |
The parent_session_id column is a self-referencing foreign key:
worker session (IO1, issues-review)
└── subagent (worker-issue #721)
└── subagent (worker-issue #722)
└── subagent (nested subagent, if any)
Required environment variables
| Variable | Source | Example values |
|---|---|---|
CLAUDE_SESSION_ID | Set by Claude Code automatically | sess_01XYZ... |
P24_WORKER_LABEL | Server startup env (systemd unit file or /etc/environment) | IO1, HS1, BMS4-1, local |
P24_ENVIRONMENT | Server startup env (systemd unit file or /etc/environment) | vps-i1, vps-h1, bms-4, local |
SUPABASE_URL | SOPS → .env on server | https://mwkqmgadqnkkihjdeqsi.supabase.co |
SUPABASE_ANON_KEY | SOPS → .env on server | eyJ... |
Why server startup env for P24_WORKER_LABEL / P24_ENVIRONMENT? These are identity labels, not secrets — safe to set as system env vars. Claude Code inherits the parent process environment, so any var set in the systemd unit or
/etc/environmentis automatically available in every session. Do NOT put them in.claude/settings.json— that file is committed and shared across all environments.
Optional:
| Variable | When to set | Notes |
|---|---|---|
P24_PARENT_SESSION_ID | Subagent sessions | Inject in subagent prompt preamble (see below) |
P24_SKILL_INVOKED | When a skill triggers the session | e.g. hourly-devops-triage |
P24_BRANCH | Session-end script | Current git branch |
P24_ISSUES_WORKED | Session-end script | Comma-separated issue numbers, e.g. 721,722 |
P24_PR_CREATED | Session-end script | PR number if one was opened |
Per-VPS setup — server startup environment
P24_WORKER_LABEL and P24_ENVIRONMENT are set in the server’s startup environment,
not in .claude/settings.json. Add them to the systemd unit file or /etc/environment
on each host:
| Host | Where to add | P24_WORKER_LABEL | P24_ENVIRONMENT |
|---|---|---|---|
| vps-i1 (IONOS) | /etc/environment or claude-runner unit | IO1 | vps-i1 |
| vps-h1 (Hostinger) | /etc/environment or claude-runner unit | HS1 | vps-h1 |
| bms-4 | /etc/environment or claude-runner unit | BMS4-1 | bms-4 |
| local (dev) | shell profile (~/.bashrc or PowerShell $PROFILE) | local | local |
Example for /etc/environment (applies to all processes on the host):
P24_WORKER_LABEL=IO1
P24_ENVIRONMENT=vps-i1
Example for a systemd unit (/etc/systemd/system/claude-runner.service):
[Service]
Environment=P24_WORKER_LABEL=IO1
Environment=P24_ENVIRONMENT=vps-i1Passing P24_PARENT_SESSION_ID to subagents
When a worker spawns a subagent via the Agent tool, include this preamble at the top of the subagent prompt:
## Session context
P24_PARENT_SESSION_ID=<current CLAUDE_SESSION_ID>
Set this env var before running agent-session-start.py so your row links
to the parent session in dev_r_agent_sessions.
The subagent reads P24_PARENT_SESSION_ID from its environment (injected via
env in the Agent tool call or written to the shell before the script runs),
sets type = 'subagent', and writes parent_session_id automatically.
Write points
Session start
Run at the beginning of each session (e.g. via a hook or skill init):
python scripts/agent-session-start.pyUpserts a row with status = 'in_progress'. Safe to call multiple times
(uses Prefer: resolution=merge-duplicates).
Session end
Run at session close (e.g. /commit skill, Stop hook):
# Normal completion
P24_BRANCH=$(git branch --show-current) \
P24_ISSUES_WORKED="721,722" \
P24_PR_CREATED="789" \
python scripts/agent-session-end.py --status completed --summary "Implemented #721 and #722, opened PR #789"
# On failure
python scripts/agent-session-end.py --status failed --summary "Blocked on missing NEXT_PUBLIC_SUPABASE_ANON_KEY"Example Grafana queries
Timeline — sessions by worker, last 24 h
SELECT
started_at,
ended_at,
worker,
environment,
status,
skill_invoked,
EXTRACT(EPOCH FROM (COALESCE(ended_at, NOW()) - started_at)) / 60 AS duration_min
FROM dev_r_agent_sessions
WHERE started_at > NOW() - INTERVAL '24 hours'
ORDER BY started_at DESC;Subagent tree — children of a given session
SELECT
s.session_id,
s.type,
s.worker,
s.skill_invoked,
s.status,
s.started_at,
s.summary
FROM dev_r_agent_sessions s
WHERE s.parent_session_id = '<parent_session_id>'
ORDER BY s.started_at;Summary table — recent worker sessions
SELECT
session_id,
worker,
environment,
skill_invoked,
status,
issues_worked,
pr_created,
EXTRACT(EPOCH FROM (COALESCE(ended_at, NOW()) - started_at)) / 60 AS duration_min,
summary,
started_at
FROM dev_r_agent_sessions
WHERE type = 'worker'
ORDER BY started_at DESC
LIMIT 50;Notes
CLAUDE_SESSION_IDavailability: this env var is set by Claude Code when the--session-idflag is used or when the harness injects it. If not available, both scripts exit silently with a stderr message — no crash, no data loss.- No secrets are stored in this table — only session metadata.
- RLS is enabled with the standard
anon allpolicy (same pattern asdev_r_services,dev_r_projects). grafana_readonlyhas SELECT access for dashboard queries.