Skip to content

Commit 079a57a

Browse files
feat(retention): add session data retention management (#106)
Adds agent-strace retention status/clean commands to enforce configurable data retention policies. Supports max_age_days, max_sessions, and max_size_mb limits, configurable via .agent-strace.yaml or CLI flags. Deletions are logged to .agent-traces/retention.log for audit trails. Closes #89 Co-authored-by: Ona <no-reply@ona.com>
1 parent 1f7faf2 commit 079a57a

5 files changed

Lines changed: 795 additions & 1 deletion

File tree

README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,8 @@ agent-strace dashboard [--last N] [--html file] Aggregate stats and trends acros
216216
agent-strace annotate <session-id> <offset> Add notes, labels, or bookmarks to events
217217
agent-strace token-budget <session-id> Check token usage against model context limit
218218
agent-strace replay [session-id] [--limit N] Replay a session (--limit caps events shown)
219+
agent-strace retention status Show session count, size, and what policy would delete
220+
agent-strace retention clean [--dry-run] Delete sessions that exceed retention limits
219221
agent-strace watch [--timeout DURATION] [--budget $] [--on-death CMD] [--rules file]
220222
Watch a live session; kill/pause on rule breach
221223
agent-strace share <session-id> [-o file] Export a self-contained HTML report
@@ -297,6 +299,39 @@ Supported models: `sonnet` (default), `opus`, `haiku`, `gpt4`, `gpt4o`. Token co
297299

298300
See [examples/session_analysis.md](examples/session_analysis.md) for a full walkthrough combining `import`, `explain`, and `cost`.
299301

302+
### Data retention
303+
304+
Enforce configurable retention policies to automatically delete old session data — required for GDPR, SOC 2, and internal data policies.
305+
306+
```bash
307+
# Check current status and what policy would delete
308+
agent-strace retention status
309+
310+
# Preview what would be deleted (no changes made)
311+
agent-strace retention clean --dry-run
312+
313+
# Delete sessions older than 30 days
314+
agent-strace retention clean --max-age-days 30
315+
316+
# Keep only the 1000 most recent sessions
317+
agent-strace retention clean --max-sessions 1000
318+
319+
# Delete oldest sessions when storage exceeds 500 MB
320+
agent-strace retention clean --max-size-mb 500
321+
```
322+
323+
Configure via `.agent-strace.yaml`:
324+
325+
```yaml
326+
retention:
327+
max_age_days: 30
328+
max_sessions: 1000
329+
max_size_mb: 500
330+
on_delete: log # log deletions to .agent-traces/retention.log
331+
```
332+
333+
Policies are applied in order: age → count → size. Deletions are logged with session ID and timestamp (not content).
334+
300335
### Secret redaction
301336
302337
Strip API keys, tokens, and credentials from traces before they hit disk.

src/agent_trace/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""agent-trace: strace for AI agents."""
22

3-
__version__ = "0.39.1"
3+
__version__ = "0.40.0"

src/agent_trace/cli.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
from .postmortem import cmd_postmortem
4646
from .share import cmd_share
4747
from .token_budget import cmd_token_budget
48+
from .retention import cmd_retention
4849
from .watch import cmd_watch
4950
from .why import cmd_why
5051
from .models import EventType, SessionMeta, TraceEvent
@@ -772,6 +773,24 @@ def build_parser() -> argparse.ArgumentParser:
772773
help="transport protocol (default: stdio)",
773774
)
774775

776+
# retention
777+
p_ret = sub.add_parser("retention", help="manage session data retention")
778+
ret_sub = p_ret.add_subparsers(dest="retention_command")
779+
780+
ret_sub.add_parser("status", help="show retention status and what would be deleted")
781+
782+
p_ret_clean = ret_sub.add_parser("clean", help="delete sessions that exceed retention limits")
783+
p_ret_clean.add_argument("--dry-run", action="store_true",
784+
help="show what would be deleted without deleting")
785+
p_ret_clean.add_argument("--max-age-days", type=int, dest="max_age_days", metavar="N",
786+
help="delete sessions older than N days")
787+
p_ret_clean.add_argument("--max-sessions", type=int, dest="max_sessions", metavar="N",
788+
help="keep only the most recent N sessions")
789+
p_ret_clean.add_argument("--max-size-mb", type=float, dest="max_size_mb", metavar="MB",
790+
help="delete oldest sessions when storage exceeds MB")
791+
p_ret_clean.add_argument("--config", metavar="FILE",
792+
help="path to .agent-strace.yaml config file")
793+
775794
# diff --semantic and --eval-config flags (extend existing diff parser)
776795
p_diff.add_argument("--semantic", action="store_true",
777796
help="semantic outcome-level diff (files, cost, errors)")
@@ -832,6 +851,7 @@ def main() -> None:
832851
"freshness": cmd_freshness,
833852
"standup": cmd_standup,
834853
"mcp": cmd_mcp,
854+
"retention": cmd_retention,
835855
}
836856

837857
handler = handlers.get(args.command)

0 commit comments

Comments
 (0)