Skip to main content

Streaming & Events

Gravity exposes a rich event stream via AgentEmitter so you can observe every step of execution in real time.

Available Events​

EventWhen it fires
run_startedAgent run begins
text_streamedModel produces a text response
tool_call_startedAgent calls a tool
tool_call_completedTool execution finishes
handoff_startedAgent hands off to another agent
guardrail_triggeredA guardrail rejected input/output
run_completedRun finishes successfully
run_failedRun fails with an error

Basic Usage​

import { AgentEmitter, Agent, DeepSeekProvider, InMemoryProvider } from 'gravity-sdk';

const emitter = new AgentEmitter();

emitter.on('run_started', (e) => {
if (e.type === 'run_started') console.log(`[${e.runId}] Run started`);
});

emitter.on('text_streamed', (e) => {
if (e.type === 'text_streamed') process.stdout.write(e.text);
});

emitter.on('tool_call_started', (e) => {
if (e.type === 'tool_call_started')
console.log(`[Tool] Calling: ${e.toolCall.name}`, e.toolCall.arguments);
});

emitter.on('tool_call_completed', (e) => {
if (e.type === 'tool_call_completed')
console.log(`[Tool] Done: ${e.result.name}`, e.result.result);
});

emitter.on('run_completed', () => console.log('\nāœ… Done'));
emitter.on('run_failed', (e) => {
if (e.type === 'run_failed') console.error(`āŒ Failed: ${e.error.message}`);
});

const agent = new Agent({
name: 'StreamBot',
instructions: 'Be helpful and concise.',
model: new DeepSeekProvider({ model: 'deepseek-v4-flash' }),
memory: new InMemoryProvider(),
emitter, // ← attach here
});

await agent.run('Tell me a joke', 'session-stream');

Building a Chat UI​

The text_streamed event is perfect for streaming token output to a frontend:

emitter.on('text_streamed', (e) => {
if (e.type === 'text_streamed') {
// Push to WebSocket, SSE stream, or React state
socket.send(JSON.stringify({ type: 'token', text: e.text }));
}
});