Tracing & Error Handling
Every Gravity agent run has a unique runId and emits structured events you can use for observability, debugging, and logging.
Run ID
Each AgentRun generates a unique UUID automatically:
emitter.on('run_started', (e) => {
if (e.type === 'run_started') {
console.log(`Run ID: ${e.runId}`);
// → Run ID: bde5cef5-f35e-4a4b-95e8-05c73a3e016f
}
});
Full Trace Logger
const emitter = new AgentEmitter();
emitter.on('run_started', (e) => log('START', e));
emitter.on('tool_call_started', (e) => log('TOOL_CALL', e));
emitter.on('tool_call_completed',(e) => log('TOOL_DONE', e));
emitter.on('handoff_started', (e) => log('HANDOFF', e));
emitter.on('guardrail_triggered',(e) => log('GUARDRAIL', e));
emitter.on('run_completed', (e) => log('DONE', e));
emitter.on('run_failed', (e) => log('FAILED', e));
function log(tag: string, event: any) {
console.log(`[${new Date().toISOString()}] [${tag}]`, JSON.stringify(event, null, 2));
}
Error Handling
Gravity throws typed errors that you can catch and handle gracefully:
try {
const result = await agent.run(userInput, sessionId);
console.log(result.output);
} catch (error: any) {
if (error.message.includes('Input rejected by guardrail')) {
// Handle blocked input
return 'Your message was rejected. Please try again.';
}
if (error.message.includes('Max iterations reached')) {
// Agent got stuck in a loop
return 'Sorry, I could not complete your request.';
}
throw error; // Re-throw unexpected errors
}
Safe Stopping Conditions
| Condition | Behavior |
|---|---|
| Model returns text (no tool calls) | Run completes normally |
Tool returns a Handoff | Run suspends and returns handoff |
maxIterations exceeded | Throws Error: Max iterations reached |
| Guardrail rejects input | Throws immediately before LLM call |
| Guardrail rejects output | Throws after model response |
Setting Max Iterations
const agent = new Agent({
name: 'SafeAgent',
maxIterations: 5, // default is 10
// ...
});