Getting started
This tutorial verifies a provider model, wraps it in reusable agent behavior, and runs both a complete and streaming response. You need an ESM-compatible TypeScript project, pnpm, and an OpenAI API key.
1. Install Anvia
Install the provider-neutral runtime and the OpenAI adapter from the stable release line.
pnpm add @anvia/core @anvia/openaiKeep the provider credential in your application's environment:
export OPENAI_API_KEY=...2. Create the model
Provider clients are explicit dependencies. They receive credentials from your configuration layer and create models that satisfy Anvia's provider-neutral completion contract.
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"
})Changing providers later only changes this construction step. The agent can continue depending on the same model interface.
3. Verify one completion
Call the model directly before adding agent behavior. This isolates credentials, model access, and provider configuration from the model/tool loop.
import { generateCompletion } from '@anvia/core'
const result = await generateCompletion({
prompt: 'Summarize Anvia in one sentence.',
model,
instructions: 'Answer clearly and concisely.'
})
console.log(result.text)generateCompletion() makes one provider call. It returns typed output, visible text, normalized content, token usage, and rawResponse; it does not run tools or save memory.
4. Define reusable agent behavior
An agent keeps instructions, limits, tools, context, and other runtime dependencies together. In v1, that configuration goes directly into the constructor.
import { Agent } from '@anvia/core'
const supportAgent = new Agent({
id: 'support',
model,
instructions: 'Answer support questions clearly. Ask for missing details.',
maxTurns: 4,
})maxTurns limits the number of model turns in a run. Tool-assisted agents often need more than one turn because the model must request a tool, receive its result, and then answer.
5. Generate an answer
generate() runs the agent until it returns a response, interaction, or guardrail block. The outcome type makes that boundary explicit.
const response = await supportAgent.generate({
prompt: 'Explain what the Anvia runtime owns.'
})
if (response.type === 'interaction') throw new Error(`Interaction required: ${response.interaction.type}`)
if (response.type === 'blocked') throw new Error(`Blocked at ${response.stage}: ${response.reason}`)
console.log(response.output)
console.log(response.usage)A response also contains normalized messages, a run ID, context usage when available, and trace metadata when tracing is enabled.
6. Stream the same agent
Use stream() when a terminal or interface should update while the run is active. It yields provider-neutral events rather than provider-specific stream chunks.
for await (const event of supportAgent.stream({
prompt: 'Draft a short launch note.'
})) {
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.usage)
}
}Agent streams can also include reasoning deltas, tool calls, tool results, turn boundaries, interaction responses, final run metadata, and errors.
Next
Continue with Core concepts to understand the runtime pieces, then Build applications when you are ready to expose the agent from a server.