DEV Community

Cover image for Agent Telemetry Is Not Agent Control
Assili Salim
Assili Salim

Posted on

Agent Telemetry Is Not Agent Control

GitHub's Copilot updates added session streaming, cost tracking, OpenTelemetry exports. Useful. But here's the thing: seeing what went wrong and stopping it before it happens are not the same layer.
You can log that an agent retried 14 times. You can't prevent call 15 from your dashboard.
This is the gap.
Telemetry = evidence. Control = prevention.
Telemetry answers: "What happened?"
Runtime control answers: "Should this next call happen?"
Both matter. They just happen at different times.

Why agents break this worse than normal LLM calls
A normal model call is done in one roundtrip. Request → response → log it → move on.
An agent runs in a loop. It calls the model, reads results, retries, delegates, switches strategies, keeps going. One bad call might look fine. The whole sequence wastes money.
Telemetry will show you this beautifully after it happens. A runtime guard stops it before.

The basic agent loop (vulnerable)
javascriptwhile (!task.done) {
const response = await provider.call({
model: task.model,
messages: task.messages,
});

telemetry.record({ runId: task.id, model, response });
task = await applyAgentStep(task, response);
}
You get evidence. Not protection.
Add a decision before the call (safer)
javascriptconst decision = guard.beforeCall({
runId: task.id,
model: task.model,
stepCount: task.steps.length,
retryCount: task.retryCount,
budgetRemaining: task.budgetRemaining,
progressState: task.progress,
});

if (!decision.allowed) {
telemetry.record({ runId: task.id, status: "stopped", reason: decision.reason });
return { status: "stopped", reason: decision.reason };
}

const response = await provider.call({ model, messages });
Placement matters. The guard decides before. Telemetry records after.

Six checks that belong before every provider call

  1. Known model pricing If you can't price it, you can't budget it. Model names matter—aliases and rewrites break cost assumptions.
  2. Task-level budget User is under monthly limit? Great. This agent run can still be wasting work. Both levels matter.
  3. Max-step limits Agents run until something stops them. A step limit isn't sophisticated. That's why it works.
  4. Retry storms Retries are good. Repeated failure loops are not. Stop similar errors after N retries.
  5. Prompt loops Agents get stuck asking nearly the same question again. The text changes. The task doesn't. Detect it.
  6. No-progress detection Track: tests passing, errors changing, tool results adding info, checklist items completing. If none move after several steps, stop.

Better telemetry includes stop reasons
Pre-call control doesn't replace telemetry. It makes telemetry better.
Record blocked calls, not just executed ones:
javascripttype AgentDecisionEvent = {
runId: string;
model: string;
stepCount: number;
allowed: boolean;
reason?: "budget_exceeded" | "retry_storm" | "prompt_loop" | "no_progress";
};
Now you can ask: Which workflows trigger prompt loops? Which teams need tighter limits? Which models have unknown pricing? That's more useful than total spend.

The takeaway
Agent observability is table stakes now. GitHub's got you there.
The next layer is admission control. Let the runtime say no before execution, not in the dashboard after.
Record what happened. Before the next call, decide if it should happen at all.

This is what AI CostGuard does—pre-call guards for production agent applications. Catches retry storms, prompt loops, budget overruns before they execute.
https://github.com/salimassili62-afk/ai-costguard

Top comments (0)