Skip to main content

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

ConditionBehavior
Model returns text (no tool calls)Run completes normally
Tool returns a HandoffRun suspends and returns handoff
maxIterations exceededThrows Error: Max iterations reached
Guardrail rejects inputThrows immediately before LLM call
Guardrail rejects outputThrows after model response

Setting Max Iterations

const agent = new Agent({
name: 'SafeAgent',
maxIterations: 5, // default is 10
// ...
});