Effect Agent
September 15, 2026 · View on GitHub
Build TypeScript agents with Effect and Effect AI. Define inputs, outputs, and tools with schemas. Effect Agent runs the loop, executes tools, and validates the result — with typed errors, streaming, and bounded execution.
Install
bun add effect-agent@beta
Use an Effect AI provider for model access.
Prefer named namespace imports from package roots, such as import { Agent } from "effect-agent".
Direct module paths use kebab-case, such as effect-agent/agent-runtime; see the
import guide for direct imports and lazy loading.
Public beta: APIs and stored data may change before 1.0. Persistent adapters support a data-preserving beta49/beta50 storage upgrade.
A basic agent
import { Effect, Schema } from "effect";
import { Agent, AgentRuntime } from "effect-agent";
import { Toolkit } from "effect/unstable/ai";
const planner = Agent.make("travel-planner", {
input: Schema.Struct({ city: Schema.String, days: Schema.Int }),
output: Schema.Struct({ itinerary: Schema.Array(Schema.String) }),
instructions: ({ city, days }) => `Plan ${days} days in ${city}. Suggest one activity per day.`,
toolkit: Toolkit.empty,
policy: { maxTurns: 6, maxToolCalls: 10, maxDuration: "2 minutes" },
});
const program = Effect.gen(function* () {
const result = yield* AgentRuntime.run(planner, { city: "Lisbon", days: 2 });
yield* Effect.log(result.output.itinerary); // readonly string[]
});
The output is schema-validated. Supply your model and runtime services to run it:
Run this example with OpenAI
Save the code above and the setup below as agent.ts.
import { InMemory } from "effect-agent";
import { OpenAiClient, OpenAiLanguageModel } from "@effect/ai-openai";
import { BunRuntime } from "@effect/platform-bun";
import { Config, Layer } from "effect";
import { FetchHttpClient } from "effect/unstable/http";
const AppLive = Layer.mergeAll(OpenAiLanguageModel.model("gpt-6-astra"), InMemory.layer).pipe(
Layer.provide(OpenAiClient.layerConfig({ apiKey: Config.Redacted("OPENAI_API_KEY") })),
Layer.provide(FetchHttpClient.layer),
);
BunRuntime.runMain(program.pipe(Effect.provide(AppLive)));
export OPENAI_API_KEY="your-api-key"
bun agent.ts
Give it tools
Use native Effect AI tools with typed parameters, results, and Effect handlers:
import { Tool } from "effect/unstable/ai";
const SearchActivities = Tool.make("search_activities", {
description: "Find activities in a city.",
parameters: Schema.Struct({ city: Schema.String }),
success: Schema.Array(Schema.String),
});
const TravelTools = Toolkit.make(SearchActivities);
const TravelToolsLive = TravelTools.toLayer({
// Sample data; replace with your database or API.
search_activities: ({ city }) =>
Effect.succeed(city === "Lisbon" ? ["Riverside walk", "Food market"] : []),
});
Define these before planner, set its toolkit to TravelTools, and add TravelToolsLive
to Layer.mergeAll above.
More about tools, approvals, and MCP →
Stream progress
Use the same agent and services to observe text, tool activity, and lifecycle events:
import { Stream } from "effect";
const streaming = AgentRuntime.stream(planner, { city: "Lisbon", days: 2 }).pipe(
Stream.runForEach((event) => Effect.log(event._tag)),
Effect.provide(AppLive),
);
BunRuntime.runMain(streaming);
Use this in place of the earlier BunRuntime.runMain call.
More about streaming and interactive input →
More examples
- Travel planner — complete agent, tools, and provider setup.
- Subagents, browser tools, and Code Mode — delegate research, browse pages, and execute code.
- Persistent threads, durable execution, and Effect Workflows — keep history and resume work.
- Cloudflare travel planner and the PR reviewer.
Start with the getting-started guide, or explore the package map and deployment guide.
Development
Framework packages live in packages/*, and runnable examples live in examples/*.
Use Vite+ for repository commands. Bun is the package manager.
vp install
vp run docs:dev
vp run ready
vp run ready runs static checks, tests, package builds, and the documentation build with link
validation. Before changing code, read the toolchain guide,
glossary, and contributor instructions.
Similar projects and inspiration
We took inspiration from Flue and Pi for parts of the agent loop, interaction model, and durability design.