"Should we log this?"
It's a question that comes up constantly when building AI agent systems. And the default answer is usually "yes, just in case."
That default is wrong. Here's a better framework.
The Logging Decision Tree
The Four Categories
Every agent activity falls into one of four categories:
1. Decisions (Always Log)
A decision is when an agent chooses between alternatives. These are high-signal by definition.
{
"type": "decision",
"agent": "support-agent",
"options_considered": ["escalate", "resolve", "request_info"],
"choice": "escalate",
"confidence": 0.87,
"reasoning": "Customer sentiment negative, issue complexity high"
}
Examples:
- Chose to approve vs deny a request
- Selected which action to take next
- Decided to escalate vs handle directly
- Prioritized one task over another
2. Outcomes (Always Log)
An outcome is the result of an agent's work. This is what you're ultimately trying to optimize.
{
"type": "outcome",
"agent": "sales-agent",
"task": "lead-qualification",
"result": "qualified",
"lead_score": 85,
"next_action": "schedule_demo"
}
Examples:
- Task completed successfully or failed
- Customer satisfied or churned
- Revenue generated or lost
- Problem resolved or escalated
3. Exceptions (Always Log)
When something goes wrong, you need to know. Exceptions are always signal.
{
"type": "exception",
"agent": "data-agent",
"error": "API_TIMEOUT",
"context": {
"endpoint": "/api/customers",
"attempt": 3,
"timeout_ms": 5000
},
"recovery_action": "retry_with_backoff"
}
4. Operations (Usually Skip)
Operations are the routine activities agents perform. Most of these are noise.
{
"type": "operation",
"agent": "email-agent",
"action": "fetch_inbox",
"emails_found": 23
}
Log if: The operation fails, takes unusually long, or produces unexpected results.
Skip if: It's routine and successful.
The Granularity Question
Even within loggable categories, granularity matters.
Too Granular (Noise)
{"event": "button_rendered", "component": "submit_button"}
{"event": "state_updated", "field": "form.email", "value": "..."}
{"event": "validation_passed", "field": "email"}
{"event": "api_call_started", "endpoint": "/submit"}
{"event": "api_call_completed", "status": 200}
{"event": "state_updated", "field": "form.submitted", "value": true}
{"event": "redirect_initiated", "path": "/success"}
Right Granularity (Signal)
{
"event": "form_submitted",
"form": "contact_request",
"result": "success",
"processing_time_ms": 234
}
One meaningful event instead of seven meaningless ones.
The "Future You" Test
Before logging something, ask: "Will future me, debugging a production issue at 2 AM, be glad this was logged?"
If the answer is "probably not," skip it.
Useful at 2 AM:
- Why did the agent make that decision?
- What was the system state when the error occurred?
- What happened in the 30 seconds before the failure?
Not useful at 2 AM:
- How many times did the agent check the cache?
- What was the exact sequence of UI renders?
- How long did each database query take (when all succeeded)?
Implementing the Framework
In Your SDK
// Good: Logs a decision
empress.logDecision({
agent: "pricing-agent",
decision: "apply_discount",
options: ["full_price", "10%_discount", "20%_discount"],
choice: "10%_discount",
reasoning: "Customer loyalty score > 80"
});
// Good: Logs an outcome
empress.logOutcome({
agent: "pricing-agent",
task: "quote_generation",
result: "accepted",
value: 4500
});
// Skip: Don't log routine operations
// empress.log({ event: "cache_checked" }); // Don't do this
In Your Agent Logic
# Before every log statement, ask:
# 1. Is this a decision, outcome, or exception?
# 2. Would I act on this information?
# 3. Is this required for compliance?
# If none of the above: don't log it.
The Result
Teams that apply this framework typically reduce their log volume by 90% while improving their ability to debug issues and prove compliance.
Less data. More insight. Lower costs. Better outcomes.
That's the goal of signal-focused observability.