Anvia

Getting Started

Install Anvia and run a complete first agent.

This guide creates a small TypeScript project, runs one Anvia agent, then adds a tool and conversation history.

1. Create a Project

mkdir anvia-quickstart
cd anvia-quickstart
pnpm init

Install Anvia and the TypeScript runner used in this guide:

pnpm add @anvia/core @anvia/openai @anvia/anthropic @anvia/gemini
pnpm add -D tsx typescript @types/node

Install zod if you want to add tools or structured output:

pnpm add zod

2. Set a Provider Key

Load provider credentials through your app's normal configuration system. Anvia clients use explicit constructor values and do not read environment variables themselves.

3. Create main.ts

Create a main.ts file:

import { AgentBuilder } from "@anvia/core";
import { OpenAIClient } from "@anvia/openai";

const client = new OpenAIClient({ apiKey });
const model = client.completionModel("gpt-5");

const agent = new AgentBuilder("support", model)
  .name("Support Agent")
  .description("Answers product support questions.")
  .instructions("Answer clearly. Ask for missing details before guessing.")
  .build();

const response = await agent
  .prompt("A user cannot reset their password. What should I check first?")
  .send();

console.log(response.output);
console.log(`Tokens: ${response.usage.totalTokens}`);

Run it:

pnpm exec tsx main.ts

You now have the basic Anvia loop:

  1. new OpenAIClient({ apiKey }) configures provider access.
  2. client.completionModel("gpt-5") creates a reusable model.
  3. AgentBuilder configures the agent.
  4. agent.prompt(...).send() runs one prompt and returns a final response.

4. Use a Different Provider

Provider clients have the same basic shape. Swap only the client and model name.

OpenAI-compatible endpoint:

import { AgentBuilder } from "@anvia/core";
import { OpenAIClient } from "@anvia/openai";

const client = new OpenAIClient({
  baseUrl,
  apiKey,
});
const model = client.completionModel("openai/gpt-5.2");

const agent = new AgentBuilder("support", model)
  .instructions("Answer clearly.")
  .build();

Anthropic:

import { AgentBuilder } from "@anvia/core";
import { AnthropicClient } from "@anvia/anthropic";

const client = new AnthropicClient({ apiKey });
const model = client.completionModel("claude-sonnet-4-20250514");

const agent = new AgentBuilder("support", model)
  .instructions("Answer clearly.")
  .build();

Gemini:

import { AgentBuilder } from "@anvia/core";
import { GeminiClient } from "@anvia/gemini";

const client = new GeminiClient({ apiKey });
const model = client.completionModel("gemini-2.5-flash");

const agent = new AgentBuilder("support", model)
  .instructions("Answer clearly.")
  .build();

Provider support can vary for attachments, streaming details, tool behavior, and model-specific parameters. Anvia normalizes the SDK surface, but it does not make every provider model identical.

5. Add Static Context

Use .context(...) for small facts that should be included with every prompt.

const agent = new AgentBuilder("support", model)
  .instructions("Use the support policy when answering.")
  .context("Password reset links expire after 30 minutes.", "password-policy")
  .build();

const response = await agent.prompt("How long does a reset link last?").send();

Use retrieval and dynamic context for larger knowledge bases.

6. Add a Tool

Tools expose application-owned behavior to the agent. Anvia validates tool input with Zod before calling your function.

import { AgentBuilder, createTool } from "@anvia/core";
import { OpenAIClient } from "@anvia/openai";
import { z } from "zod";

const lookupOrder = createTool({
  name: "lookup_order",
  description: "Look up an order by order id.",
  input: z.object({
    orderId: z.string().describe("The order id to inspect."),
  }),
  output: z.object({
    status: z.string(),
    carrier: z.string().optional(),
  }),
  async execute({ orderId }) {
    return {
      status: orderId === "A-100" ? "shipped" : "unknown",
      carrier: "DHL",
    };
  },
});

const client = new OpenAIClient({ apiKey });
const model = client.completionModel("gpt-5");

const agent = new AgentBuilder("support", model)
  .instructions("Use tools when order status is needed.")
  .tool(lookupOrder)
  .defaultMaxTurns(3)
  .build();

const response = await agent.prompt("Where is order A-100?").send();

console.log(response.output);

defaultMaxTurns(3) gives the agent room to ask the model, run the tool, and ask the model for the final answer. Keep turn limits low until the workflow is well understood.

7. Persist History

Anvia history is a plain Message[]. Store it wherever your application stores conversations.

const history = await conversations.loadMessages(conversationId);

const response = await agent
  .prompt(userInput)
  .withHistory(history)
  .send();

await conversations.saveMessages(conversationId, [
  ...history,
  ...response.messages,
]);

response.messages contains only the new prompt, assistant messages, and tool result messages created during the run. Append it to your stored history when you want the next turn to remember it.

8. Common Mistakes

MistakeBetter approach
Creating a provider client for every promptCreate clients and models once, then reuse them
Saving only response.outputSave response.messages when you need conversation history
Putting large knowledge bases in .context(...)Use retrieval and dynamic context
Letting tools perform unchecked side effectsEnforce product permissions inside tool code
Setting high turn limits immediatelyStart low and increase only when the workflow needs it

9. Next Steps

Read these next:

  1. Build an Agent
  2. Add Tools
  3. Persist Conversations
  4. Return Structured Output
  5. Prepare for Production