stratus

Introduction

A TypeScript agent SDK for Azure OpenAI

Stratus is a TypeScript SDK for building AI agents powered by Azure OpenAI. It provides a clean, composable API for multi-turn conversations, tool use, multi-agent handoffs, streaming, guardrails, and tracing.

Why this exists

Azure OpenAI's v1 API lets you use the standard OpenAI() client, point it at your Azure endpoint, and things mostly just work. But "mostly" isn't good enough for production.

The OpenAI SDK gives you chat.completions.create(). Everything else - the tool loop, agent abstractions, streaming, error handling, multi-agent orchestration - is on you:

  • Tool calling requires a manual loop. Stratus handles the entire tool loop - one run() call with parallel execution, validation, and error recovery.
  • No agent abstraction. Stratus gives you composable agents with instructions, tools, guardrails, and handoffs in a single config object.
  • Basic streaming. Stratus provides typed stream events - content_delta, tool_call_start, tool_call_done - with accumulation and a final RunResult.
  • Opaque content filter errors. Stratus throws a typed ContentFilterError instead of Azure's buried inner_error.content_filter_results.
  • No multi-agent orchestration. Handoffs, subagents, guardrails, and hooks are first-class.
  • Responses API support. Both Chat Completions and Responses API through the same Model interface - swap with one line.

The goal: clean, typed, zero-config for the common case - while properly wrapping Azure's unique capabilities.

Features

Quick Example

weather-agent.ts
import { AzureChatCompletionsModel } from "stratus";
import { createSession, tool } from "stratus/core";
import { z } from "zod";

const model = new AzureChatCompletionsModel({
  endpoint: process.env.AZURE_ENDPOINT!,
  apiKey: process.env.AZURE_API_KEY!,
  deployment: "gpt-5.2",
});

const getWeather = tool({
  name: "get_weather",
  description: "Get current weather for a city",
  parameters: z.object({ city: z.string() }),
  execute: async (_ctx, { city }) => `72°F and sunny in ${city}`,
});

await using session = createSession({
  model,
  instructions: "You are a weather assistant.",
  tools: [getWeather],
});

session.send("What's the weather in NYC?");
for await (const event of session.stream()) {
  if (event.type === "content_delta") process.stdout.write(event.content);
}

// Multi-turn: context persists automatically
session.send("What about London?");
for await (const event of session.stream()) {
  if (event.type === "content_delta") process.stdout.write(event.content);
}

Architecture

Stratus is organized into two layers:

PackageDescription
stratus/coreProvider-agnostic: Agent, Session, run loop, tools, handoffs, guardrails, hooks, tracing
stratusRe-exports core + Azure OpenAI implementation

The core layer defines the Model interface. Azure is the built-in implementation, but you can plug in any provider by implementing Model.

Guides

End-to-end examples showing how to combine features into real agents:

Project Structure

agent.ts
run.ts
session.ts
tool.ts
subagent.ts
handoff.ts
hooks.ts
guardrails.ts
tracing.ts
cost.ts
types.ts
model.ts
errors.ts
Edit on GitHub

Last updated on

On this page