A multi-process information aggregation pipeline (scrapers → LLM extraction → knowledge graph) migrated from stdlib logging to AgenticLogger. Observed over 24h with ~100K entries / 180 MB:
Dimension
stdlib logging
AgenticLogger
Per-entry size
~150–300 bytes
80–120 bytes (**40–50% smaller**)
LLM token cost
Raw-text formatting overhead
TSV output ~46% smaller than JSONL
Cross-process tracing
Manual timestamp correlation
trace --rid walks call chains across files
Aggregation
Hand-rolled awk
stats --group-by error_code/module/tool
Third-party logs (httpx/urllib3/…)
Each library logs independently
Forwarded into the same JSONL via a stdlib handler (deployment-local helper, not shipped)
Outcome: stats --group-by error_code immediately surfaced a real bug — FRONTMATTER_TOO_DEEP (metadata nesting exceeded the storage backend’s depth limit) across 57 ERROR entries — diagnosed in a single LLM turn instead of multi-step grep chains.
Verdict: Not substitutes. For human consumers, stdlib + ELK/Grafana remains more mature (zero-dependency, plain-text tail -f). For agent/LLM consumers, AgenticLogger’s token savings, structured queries, and cross-process trace are decisive — roughly an order of magnitude fewer tokens for log-driven diagnosis.
AgenticLogger ships write-side SDKs for Bash, Rust, Go, TypeScript/JavaScript,
SystemVerilog/Verilog, and Tcl. Every SDK emits the same byte-compatible JSONL,
so logs written by any of them are read by the Python query layer (cli /
mcp_server) with zero conversion.
The canonical byte-level contract that all SDKs share is
sdks/INTERCHANGE.md. The key invariant: separators are
": " and ", " (matching Python json.dumps), pid is a string, numeric
fields are unquoted, and non-ASCII is written as raw UTF-8 (no \uXXXX). This
is what makes the Python stats byte-counter work across languages.
Verify cross-language interop:
./tests/cross_lang/run_all.sh # each SDK emits a sample → validated → read by Python CLI
Microsecond precision prevents collisions when multiple instances start in the same second.
5. Configuration
Environment Variables
Variable
Description
Default
AGENTIC_STORAGE
Force storage backend: jsonl, sqlite, auto
auto
AGENTIC_LOG_DIR
Default log directory
./logs
AGENTIC_SELF_LOG
Self-observation: AgenticLogger logs its own CLI/MCP operations. Set 0 to disable
1 (on)
Programmatic Configuration
from pathlib import Path
from agentic_logger import AgentLogger
from agentic_logger.storage import JSONLBackend, SQLiteBackend
# Backend selection via string — AgentLogger builds the backend internally
logger = AgentLogger(
program="my_agent",
command="run",
log_dir="./custom_logs",
storage="jsonl", # or "sqlite", or "auto" (default)
circular=True,
max_size_mb=100,
max_files=5,
)
# Backend classes are exported for custom integrations:
backend = SQLiteBackend(file_path=Path("./logs/my.sqlite"), global_ctx={"program": "my_agent"})
Self-Observability (Dogfooding)
AgenticLogger logs its own read-layer operations (every CLI command, every MCP
tool dispatch) using the AgentLogger SDK itself — closing the loop. These
self-log entries land alongside your logs in the same log_dir with
program="agentic_logger" (e.g. agentic_logger_mcp_*.jsonl,
agentic_logger_query_*.jsonl), so they are part of the queryable dataset.
Why it matters (token + iteration efficiency): when AgenticLogger itself
misbehaves, one targeted query surfaces the cause — no log spelunking, no
repeated reads.
# All self errors in one shot (rid + error_code + duration included)
agentic-logger query --module "agentic_logger.*" --level ERROR --depth detail
# Full chronological trace of one MCP server session (by rid)
agentic-logger trace --rid <rid>
# Distribution of self tool / command calls
agentic-logger stats --group-by module --module "agentic_logger.*"
# Smart aggregation of self error patterns + suggestions
agentic-logger query --module "agentic_logger.*" --smart
Self-log fields captured per call: tool/command, exit, dur_ms,
results, backends, compact args, and error on failure. Files are
circular-bounded (max_files=10). Disable with AGENTIC_SELF_LOG=0.
6. Best Practices
Always use error_code for errors — enables aggregation and alerting
Use tool_call() for all external commands — captures exit code, duration, command
Use file_op() for file I/O — tracks reads/writes/deletes with paths
Use decision() for architectural choices — creates audit trail
Set command in AgentLogger — groups logs by logical run (build, test, deploy)
Enable circular mode for long-running daemons — prevents unbounded disk usage
Use ctx for structured context — avoids log message parsing
# Install with dev dependencies
uv sync --extra dev --extra mcp
# Run tests
uv run pytest tests/ -v
# Check coverage
uv run pytest tests/ --cov=agentic_logger
# Lint
uv run ruff check src/
Code Conventions
Inline Spec Annotations
Source files use inline spec tags for drift detection and grep-based discovery:
Tag
Purpose
@spec-ref
Points to arch spec section (file#section)
@spec-why
Reasoning behind non-obvious decisions
@spec-invariant
What the function deliberately does NOT do
@spec-caution
Cross-file/cross-repo dependencies
@agent-tag
Functional category for grep discovery (sparse, critical paths only)
@agent-caution
Risk warnings for future edits
@agent-todo
Agent-facing action reminders
@last-changed
Single timestamp of most recent substantive change (ISO 8601)
@log-module
Retrieval metadata linking to log entries
Density principle: Every tag/comment line must be terse — no filler words, no restating the obvious. If content exceeds ~2 lines, question whether it belongs inline or in the arch spec.
Drift detection: Before editing code with @spec-* tags, read them as constraints. After editing, verify the new behavior still satisfies @spec-invariant and matches the section cited in @spec-ref. If not, follow the conflict resolution process (present to user, don’t silently rewrite specs).
License
PolyForm Noncommercial 1.0.0 — free for personal and noncommercial use; commercial use requires a separate license from the author (Universe Zero). Contributions via PR are welcome and are licensed under the same terms. Prior releases (≤ 0.1.3) were published under MIT and remain MIT-licensed.
AgenticLogger
Structured logging for Coding Agents — write once, read efficiently.
AgenticLogger lets Coding Agents (Claude Code, Cursor, Copilot, etc.) emit structured logs that AI tools can query with minimal token overhead. Instead of parsing free-form text, agents read pre-structured JSON entries with indexed fields.
Quick Start
Log file:
./logs/my_agent_build_20260721_133834090719.jsonlCase Study: Real-World Deployment
A multi-process information aggregation pipeline (scrapers → LLM extraction → knowledge graph) migrated from stdlib
loggingto AgenticLogger. Observed over 24h with ~100K entries / 180 MB:logging80–120 bytes (**40–50% smaller**)trace --ridwalks call chains across filesawkstats --group-by error_code/module/toolOutcome:
stats --group-by error_codeimmediately surfaced a real bug —FRONTMATTER_TOO_DEEP(metadata nesting exceeded the storage backend’s depth limit) across 57 ERROR entries — diagnosed in a single LLM turn instead of multi-stepgrepchains.Verdict: Not substitutes. For human consumers, stdlib + ELK/Grafana remains more mature (zero-dependency, plain-text
tail -f). For agent/LLM consumers, AgenticLogger’s token savings, structured queries, and cross-process trace are decisive — roughly an order of magnitude fewer tokens for log-driven diagnosis.→ Full report: docs/case-studies/agenticlogger-vs-stdlib-logging.md
Installation
For detailed installation instructions, see Installation Guide.
Quick Install
From Source (Development)
This installs the package in editable mode with development dependencies and the MCP server extra.
Verify Installation
Multi-Language SDKs
AgenticLogger ships write-side SDKs for Bash, Rust, Go, TypeScript/JavaScript, SystemVerilog/Verilog, and Tcl. Every SDK emits the same byte-compatible JSONL, so logs written by any of them are read by the Python query layer (
cli/mcp_server) with zero conversion.sdks/bashagentic_logger.sh(sourceable)sdks/rustagentic-loggercratesdks/gogithub.com/amoslee2026/AgenticLogger/sdks/gosdks/tsagentic-logger(npm, ESM + types)sdks/systemverilogagentic_logger_pkg.sv+ DPI-Csdks/tclagentic_logger.tcl(sourceable)The canonical byte-level contract that all SDKs share is
sdks/INTERCHANGE.md. The key invariant: separators are": "and", "(matching Pythonjson.dumps),pidis a string, numeric fields are unquoted, and non-ASCII is written as raw UTF-8 (no\uXXXX). This is what makes the Pythonstatsbyte-counter work across languages.Verify cross-language interop:
See
sdks/README.mdfor the API map and per-SDK install.User Guide
1. Writing Logs (Python SDK)
Basic Logger Setup
Circular Write Mode (Long-Running Agents)
Log Methods by Use Case
info()logger.info("Starting build", module="build")warn()logger.warn("Deprecated API used", module="api")error()logger.error("Build failed", module="build", error_code=ErrorCode.EXEC_NON_ZERO)exception()try: ... except Exception: logger.exception("Failed", ErrorCode.UNKNOWN)tool_call()logger.tool_call("bash", "npm install", exit=0, dur=5000)file_op()logger.file_op("write", "/path/file.py", ok=True)decision()logger.decision("use_redis", ["redis", "memcached"], "better perf")code_gen()logger.code_gen("python", "gen/model.py", lines=150)context_switch()logger.context_switch("test", "build")Context Dictionary (
ctx)All methods accept a
ctxdict for structured metadata:Error Codes
Use standardized error codes from
ErrorCodeenum for consistent error categorization:See Error Code Taxonomy for the full list.
2. Reading Logs
CLI (Human-Friendly)
Common Options:
--log-dir— Log directory (default:./logs)--format— Output format:table(default) orjson--since/--until— Time range (ISO 8601 or relative:1h,24h,7d)MCP Server (For AI Agents)
Start the MCP server (stdio transport):
Configure in your AI client (e.g., Claude Code):
Available MCP Tools:
agentic_log_queryagentic_log_traceridagentic_log_statsagentic_log_tracebacktidPython SDK (Programmatic Access)
3. Storage Backends
tail -f, grep/jqAuto-selection rules (first match wins):
AGENTIC_STORAGEenv var.sqlitefiles for same program → SQLitebuild,test,ci,lint,deploy) → SQLite4. Log File Naming
Format:
{program}_{command}_{YYYYMMDD}_{HHmmssffffff}.{ext}Examples:
my_agent_main_20260721_133834090719.jsonlbuild_script_test_20260721_140000123456.sqliteMicrosecond precision prevents collisions when multiple instances start in the same second.
5. Configuration
Environment Variables
AGENTIC_STORAGEjsonl,sqlite,autoautoAGENTIC_LOG_DIR./logsAGENTIC_SELF_LOG0to disable1(on)Programmatic Configuration
Self-Observability (Dogfooding)
AgenticLogger logs its own read-layer operations (every CLI command, every MCP tool dispatch) using the
AgentLoggerSDK itself — closing the loop. These self-log entries land alongside your logs in the samelog_dirwithprogram="agentic_logger"(e.g.agentic_logger_mcp_*.jsonl,agentic_logger_query_*.jsonl), so they are part of the queryable dataset.Why it matters (token + iteration efficiency): when AgenticLogger itself misbehaves, one targeted query surfaces the cause — no log spelunking, no repeated reads.
Self-log fields captured per call:
tool/command,exit,dur_ms,results,backends, compactargs, anderroron failure. Files are circular-bounded (max_files=10). Disable withAGENTIC_SELF_LOG=0.6. Best Practices
error_codefor errors — enables aggregation and alertingtool_call()for all external commands — captures exit code, duration, commandfile_op()for file I/O — tracks reads/writes/deletes with pathsdecision()for architectural choices — creates audit trailcommandinAgentLogger— groups logs by logical run (build, test, deploy)ctxfor structured context — avoids log message parsing7. Log Analysis Utilities
The
utils/directory provides token-efficient log analysis (per Token Saving Rules):utils/log_triage.py./utils/log_triage.py <logfile>utils/log_extract.sh./utils/log_extract.sh <logfile> [pattern]utils/agentic_logger.pyfrom utils.agentic_logger import get_loggerRecommended workflow:
log_triage.pyto identify error typeslog_extract.shto pull context around specific patternsCore Concepts
Structured Log Entries
Each log entry is a single JSON line with auto-filled fields:
tslevelINFO,WARN,ERROR,TOOL,FILE_OP,DECISION,CODE_GEN,CONTEXTmsgmoduleridpidseqdurerror_codeErrorCodeenum)ctxLog Methods
info(msg, ...)warn(msg, ...)error(msg, error_code, ...)exception(msg, error_code)tool_call(tool, cmd, exit, dur, ...)file_op(op, path, ok, ...)decision(choice, alts, reason)code_gen(lang, path, ...)context_switch(to_task, from_task)Error Code Taxonomy
See
src/agentic_logger/error_codes.pyfor the complete error code list.Architecture
Development
Code Conventions
Inline Spec Annotations
Source files use inline spec tags for drift detection and grep-based discovery:
@spec-ref@spec-why@spec-invariant@spec-caution@agent-tag@agent-caution@agent-todo@last-changed@log-moduleDensity principle: Every tag/comment line must be terse — no filler words, no restating the obvious. If content exceeds ~2 lines, question whether it belongs inline or in the arch spec.
Drift detection: Before editing code with
@spec-*tags, read them as constraints. After editing, verify the new behavior still satisfies@spec-invariantand matches the section cited in@spec-ref. If not, follow the conflict resolution process (present to user, don’t silently rewrite specs).License
PolyForm Noncommercial 1.0.0 — free for personal and noncommercial use; commercial use requires a separate license from the author (Universe Zero). Contributions via PR are welcome and are licensed under the same terms. Prior releases (≤ 0.1.3) were published under MIT and remain MIT-licensed.