First Turn
This page walks through creating an agent, submitting a turn, and consuming the event stream.
Create an agent
import { createAgent } from 'apeira'
import { responses } from 'apeira/responses'
const agent = createAgent({
instructions: 'You are a concise assistant.',
runner: responses({
apiKey: process.env.OPENAI_API_KEY,
baseURL: 'https://api.openai.com/v1/',
model: 'gpt-5.5',
}),
})responses() configures the Responses backend. See Runners for choosing between responses() and chat(), or using provider presets. Apeira manages input, instructions, and abortSignal internally.
Run a turn
run() submits one user turn and returns a ReadableStream of events for that turn.
import { createAgent, run } from 'apeira'
import { responses } from 'apeira/responses'
const agent = createAgent({
instructions: 'You are a concise assistant.',
runner: responses({
apiKey: process.env.OPENAI_API_KEY,
baseURL: 'https://api.openai.com/v1/',
model: 'gpt-5.5',
}),
})
const stream = run(agent, {
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.
import { createAgent } from 'apeira'
import { responses } from 'apeira/responses'
const agent = createAgent({
instructions: 'You are a concise assistant.',
runner: responses({
apiKey: process.env.OPENAI_API_KEY,
baseURL: 'https://api.openai.com/v1/',
model: 'gpt-5.5',
}),
})
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 a turn is already active, send() queues the input for that turn and returns the existing turn ID. If no turn is active, it creates a new top-level turn.
Per-turn abort
Pass an AbortSignal to abort a specific turn:
import { createAgent, run } from 'apeira'
import { responses } from 'apeira/responses'
const agent = createAgent({
instructions: 'You are a concise assistant.',
runner: responses({
apiKey: process.env.OPENAI_API_KEY,
baseURL: 'https://api.openai.com/v1/',
model: 'gpt-5.5',
}),
})
const controller = new AbortController()
run(agent, {
content: 'Say hello.',
role: 'user',
type: 'message',
}, { signal: controller.signal })
controller.abort('cancelled')Cancelling the ReadableStream reader only stops reading events. It does not abort the running turn.
