Streaming & Events
Gravity exposes a rich event stream via AgentEmitter so you can observe every step of execution in real time.
Available Eventsā
| Event | When it fires |
|---|---|
run_started | Agent run begins |
text_streamed | Model produces a text response |
tool_call_started | Agent calls a tool |
tool_call_completed | Tool execution finishes |
handoff_started | Agent hands off to another agent |
guardrail_triggered | A guardrail rejected input/output |
run_completed | Run finishes successfully |
run_failed | Run 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 }));
}
});