Learning Paths
Prepare for Production
Review practical checks before shipping Anvia workflows.
Use this path when an Anvia workflow is moving from a prototype into product code.
Goal
By the end, you should have reviewed:
- provider configuration
- tool permissions
- history persistence
- turn limits
- structured output validation
- retries and error handling
- logging and traces
Checklist
| Area | Check |
|---|---|
| Providers | Create clients and models once, configure keys through your normal secret system |
| Tools | Enforce auth and permissions inside tool code |
| History | Persist Message[] and append response.messages |
| Turn limits | Keep limits low enough to prevent unbounded tool loops |
| Structured output | Validate output before using it in product workflows |
| Retrieval | Filter by tenant, user, or document ownership when needed |
| Observability | Log run metadata, usage, tool calls, errors, and trace ids |
| Errors | Classify setup, provider, validation, tool, and runtime-limit failures |
Path
- Read Runtime Boundaries to confirm ownership is clear.
- Read Errors to plan failure handling.
- Read Human in the Loop for guarded actions.
- Read Messages and History for persistence shape.
- Read Output Validation for typed workflows.
- Read Observers for runtime visibility.
Practical Rule
Keep product-critical decisions in your application code. Use Anvia to coordinate prompts, tools, context, retrieval, output shape, and observability around those decisions.
Runtime Wrapper Shape
Put agent calls behind a small application-owned wrapper so logging, history, trace metadata, and error handling are consistent.
import {
MaxTurnsError,
PromptCancelledError,
type Agent,
type Message,
} from "@anvia/core";
type RunSupportAgentOptions = {
userId: string;
conversationId: string;
input: string;
history: Message[];
};
export async function runSupportAgent(
agent: Agent,
options: RunSupportAgentOptions,
) {
try {
const response = await agent
.prompt(options.input)
.withHistory(options.history)
.withTrace({
name: "support-agent",
userId: options.userId,
sessionId: options.conversationId,
})
.maxTurns(3)
.send();
await conversations.saveMessages(options.conversationId, [
...options.history,
...response.messages,
]);
await usageEvents.record({
userId: options.userId,
totalTokens: response.usage.totalTokens,
traceId: response.trace?.traceId,
});
return response.output;
} catch (error) {
if (error instanceof MaxTurnsError) {
await incidents.record("support-agent-max-turns", error);
return "The support workflow could not finish safely.";
}
if (error instanceof PromptCancelledError) {
return "The support request was cancelled.";
}
await incidents.record("support-agent-failed", error);
throw error;
}
}Keep the wrapper small. It should coordinate application policy around the agent, not hide all SDK concepts from the rest of the codebase.
