First Turn
This page walks through creating an agent, submitting a turn, and consuming the event stream.
Create an agent
import { createAgent } from 'apeira'
const agent = createAgent({
instructions: 'You are a concise assistant.',
name: 'assistant',
options: {
apiKey: process.env.OPENAI_API_KEY,
baseURL: 'https://api.openai.com/v1/',
model: 'gpt-5.5',
},
})options are forwarded to @xsai-ext/responses for model configuration. Apeira manages input, instructions, and abortSignal internally — you do not need to set them here.
Run a turn
run() submits one user turn and returns a ReadableStream of events for that turn.
const stream = agent.run({
content: 'Say hello.',
role: 'user',
type: 'message',
})
for await (const event of stream) {
console.log(event.turnId, event.type)
}The stream emits model events (text.delta, tool-call.start, etc.) and lifecycle events (turn.start, turn.done). It closes after turn.done, turn.failed, or turn.aborted.
Fire-and-forget with send
Use send() when you only want the turn ID and plan to observe events through a global subscription.
const unsubscribe = agent.subscribe('apeira', (event) => {
console.log(event.turnId, event.type)
})
const turnId = agent.send({
content: 'Say hello.',
role: 'user',
type: 'message',
})
// later
unsubscribe()If no turn is active or scheduled, send() creates a new top-level turn. If a turn is already active or scheduled, it queues the input for that turn and returns the existing turn ID.
Per-turn abort
Pass an AbortSignal to abort a specific turn:
const controller = new AbortController()
agent.run(input, { signal })
controller.abort('cancelled')Cancelling the ReadableStream reader only stops reading events. It does not abort the running turn.