Your first agent ​
This tutorial turns a working provider model into a reusable agent with a stable identity, instructions, bounded execution, and normalized runtime results.
Complete Install and setup first. You should already have a provider model that can perform a direct completion.
1. Construct the agent ​
Pass the provider model and reusable behavior directly to the v1 Agent constructor.
import { Agent } from '@anvia/core'
import { OpenAIClient } from '@anvia/openai'
const apiKey = process.env.OPENAI_API_KEY
if (!apiKey) {
throw new Error('OPENAI_API_KEY is required')
}
const client = new OpenAIClient({ apiKey })
const model = client.completionModel({
modelId: 'gpt-5.6-sol',
api: "responses"
})
const supportAgent = new Agent({
id: 'support',
model,
instructions: 'Answer support questions clearly. Ask for missing details.',
maxTurns: 4,
})Each option has a distinct responsibility:
idgives runs, sessions, Studio, and observability a stable agent identity.modelsupplies the provider-backed completion implementation.instructionsdefine behavior reused across runs.maxTurnsbounds the default model and tool loop.
Tools, memory, context, guardrails, middleware, and observers can be added to the same options object later.
2. Generate the first answer ​
generate() starts a run and resolves to a response, interaction, or guardrail block.
const response = await supportAgent.generate({
prompt: 'What information do you need to investigate a failed checkout?'
})
if (response.type === 'interaction') {
const resumed = await supportAgent.resume(
response.continuation,
{ type: 'tool-approval', approved: true }
)
if (resumed.type === 'response') {
console.log(resumed.output)
}
} else if (response.type === 'blocked') {
throw new Error(`Blocked at ${response.stage}: ${response.reason}`)
} else {
console.log(response.output)
}This agent has no guardrails or interaction-capable tools, so the expected type is response. The checks keep the code correct when capabilities are added later.
An interaction pauses the run: the outcome carries the pending interaction request and a continuation. Agent.resume(continuation, response) (or generate({ continuation, response })) submits the answer and continues the run. A resumed outcome has a fresh runId and a resumedFrom: { runId, interactionId } link to the paused run. The response shape matches the request: { type: 'tool-approval', approved } for approvals, { type: 'tool-question', answers } for questions.
3. Read the run result ​
A response outcome includes more than the visible answer:
if (response.type === 'response') {
console.log({
runId: response.runId,
output: response.output,
messages: response.messages,
usage: response.usage,
contextUsage: response.contextUsage,
})
}Store or expose only the fields the application needs. Messages and model output may contain sensitive user or product data.
4. Override a limit for one run ​
Agent options define reusable defaults. Per-run options can tighten behavior without mutating the agent.
const shortResponse = await supportAgent.generate({
prompt: 'Give the first troubleshooting step only.',
maxTurns: 1
})Use conservative defaults in production and increase limits only for flows that demonstrate a need for additional turns.
5. Stream an answer ​
Use stream() when a terminal or interface should update as the run progresses.
for await (const event of supportAgent.stream({
prompt: 'Draft a short customer reply.'
})) {
if (event.type === 'text_delta') {
process.stdout.write(event.delta)
}
if (event.type === 'response' || event.type === 'interaction' || event.type === 'blocked') {
process.stdout.write('\n')
console.log(event.runId, event.usage)
}
}The same stream may later include reasoning, tool calls, tool results, interaction responses, turn boundaries, and errors.
stream() returns an AgentStream handle with more than iteration: .textStream yields only text chunks, .text and .result resolve to the final text and outcome as promises, and .result rejects if the run fails. steer(input) queues additional input mid-run and returns a { id, status: 'queued' } receipt; cancel(reason?) stops the run.
Choose the next capability ​
- Add application actions with Tools.
- Preserve conversation history with Memory.
- Attach stable documents through Context.
- Send runtime events to an interface with Streaming.
- Learn the full execution sequence in Runtime lifecycle.