@anvia/studio

Studio UI and HTTP runtime for Anvia agents.

@anvia/studio provides a local playground for testing agents, browsing sessions and traces, approving tool calls, and inspecting agent context. It runs as an HTTP server with a React-based UI.

Install

pnpm add @anvia/studio

Studio depends on @anvia/core, @anvia/react, and @anvia/server. It bundles a Hono HTTP server and a React UI.

Quick Start

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

const client = new OpenAIClient({ apiKey });
const agent = new AgentBuilder("support", client.completionModel())
  .instructions("Answer support questions.")
  .build();

const studio = new Studio({ agents: [agent] });
await studio.start();  // starts on http://localhost:3456

Open the URL in your browser to access the Studio UI.

Configuration

type StudioConfig = {
  agents: Agent[];              // agents to register
  port?: number;                // HTTP port (default: 3456)
  host?: string;                // bind address (default: "localhost")
  sessionStore?: StudioSessionStore;  // custom session persistence
  traceStore?: StudioTraceStore;      // custom trace persistence
};
const studio = new Studio({
  agents: [supportAgent, salesAgent],
  port: 8080,
  host: "0.0.0.0",
});

Studio Observer

StudioTraceObserver captures traces for the Studio UI:

import { StudioTraceObserver } from "@anvia/studio";

const observer = new StudioTraceObserver();

const agent = new AgentBuilder("support", model)
  .observe(observer)
  .build();

The observer stores traces in memory by default. Pass a custom traceStore to Studio for persistence.

Sessions

Studio tracks conversation sessions. Each session stores message history, agent configuration, and metadata.

Session Store

import { createSqliteSessionStore } from "@anvia/studio";

const sessionStore = createSqliteSessionStore("./studio.db");

const studio = new Studio({
  agents: [agent],
  sessionStore,
});

The default session store is in-memory (sessions are lost when the server restarts).

Traces

Studio captures and displays:

  • Agent run start/end with full prompt and history
  • Model generations with input/output, token usage, and latency
  • Tool calls with arguments, results, and timing
  • Errors with stack traces and partial context

Trace Store

import type { StudioTraceStore } from "@anvia/studio";

const traceStore: StudioTraceStore = {
  async save(trace) { /* persist */ },
  async load(traceId) { /* retrieve */ },
  async list(options) { /* list with filters */ },
};

const studio = new Studio({ agents: [agent], traceStore });

Approvals

Studio supports human-in-the-loop approval for tool calls. When an agent tool requires approval, Studio pauses the run and shows an approval UI.

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

const agent = new AgentBuilder("support", model)
  .tool(deleteAccountTool)
  .onToolCall(async ({ toolName }) => {
    if (toolName === "delete_account") {
      return { type: "approve" as const };  // or "reject"
    }
    return { type: "auto" as const };
  })
  .build();

When running in Studio, approval requests appear in the UI. When running outside Studio, the hook resolves immediately.

HTTP API

Studio exposes these endpoints:

EndpointMethodPurpose
/api/chatPOSTSend a message to an agent
/api/sessionsGET/POSTList/create sessions
/api/sessions/:idGETGet session details
/api/tracesGETList traces
/api/traces/:idGETGet trace details
/api/healthGETHealth check

The chat endpoint returns a JSONL event stream compatible with @anvia/react's useChat.

Programmatic Runtime

Use Studio programmatically (without the UI) for testing:

import { Studio } from "@anvia/studio";

const studio = new Studio({ agents: [agent] });
const runtime = studio.runtime;

// Send a message programmatically
const events = runtime.chat({
  agentId: "support",
  message: "Hello",
  sessionId: "test-session",
});