Skip to content

Yielded Agent

Yielded Agent

An agent harness toolkit for TypeScript, built on Effect and Effect AI.

Get startedIntroduction
bun add @yielded/agent@beta

planner.ts
import {
import AnthropicLanguageModel
AnthropicLanguageModel
} from "@effect/ai-anthropic";
import {
import Agent
Agent
,
import AgentRuntime
AgentRuntime
} from "@yielded/agent";
import {
import Effect
Effect
,
import Schema
Schema
} from "effect";
import {
const AppLive: Layer<Handler<"search_activities"> | ThreadHistory | Store | SubagentReservations | AnthropicClient, ConfigError, never>
AppLive
} from "./setup";
import {
const TravelTools: Toolkit<{
readonly search_activities: Tool<"search_activities", {
readonly parameters: Schema.Struct<{
readonly city: Schema.String;
}>;
readonly success: Schema.$Array<Schema.String>;
readonly failure: Schema.Never;
readonly failureMode: "error";
}, never>;
}>
TravelTools
} from "./tools";
export const
const TravelPlanner: Agent.Definition<Schema.Struct<{
readonly city: Schema.String;
readonly days: Schema.Int;
}>, Schema.Struct<{
readonly itinerary: Schema.$Array<Schema.String>;
}>, ({ city, days }: {
readonly city: string;
readonly days: number;
}) => string, Toolkit<{
readonly search_activities: Tool<"search_activities", {
readonly parameters: Schema.Struct<{
readonly city: Schema.String;
}>;
readonly success: Schema.$Array<Schema.String>;
readonly failure: Schema.Never;
readonly failureMode: "error";
}, never>;
}>, undefined, undefined, undefined> & {
...;
}
TravelPlanner
=
import Agent
Agent
.
function make<"travel-planner", Schema.Struct<{
readonly city: Schema.String;
readonly days: Schema.Int;
}>, Schema.Struct<{
readonly itinerary: Schema.$Array<Schema.String>;
}>, ({ city, days }: {
readonly city: string;
readonly days: number;
}) => string, Toolkit<{
readonly search_activities: Tool<"search_activities", {
readonly parameters: Schema.Struct<{
readonly city: Schema.String;
}>;
readonly success: Schema.$Array<Schema.String>;
readonly failure: Schema.Never;
readonly failureMode: "error";
}, never>;
}>, undefined>(id: "travel-planner", options: Agent.DefinitionOptions<...> & {
...;
}): Agent.Definition<...> & {
...;
} (+3 overloads)

Validate an agent ID and return a shallowly frozen, model-agnostic definition.

make
("travel-planner", {
DefinitionOptions<Struct<{ readonly city: String; readonly days: Int; }>, Struct<{ readonly itinerary: $Array<String>; }>, ({ city, days }: { readonly city: string; readonly days: number; }) => string, Toolkit<...>, undefined, undefined, undefined>.input: Schema.Struct<{
readonly city: Schema.String;
readonly days: Schema.Int;
}>
input
:
import Schema
Schema
.
function Struct<{
readonly city: Schema.String;
readonly days: Schema.Int;
}>(fields: {
readonly city: Schema.String;
readonly days: Schema.Int;
}): Schema.Struct<{
readonly city: Schema.String;
readonly days: Schema.Int;
}>

Defines a struct schema from a map of field schemas.

Details

Each field value is a schema. Use

optionalKey

or

optional

to mark fields as optional, and

mutableKey

to mark them as mutable.

The resulting schema's Type is a readonly object type with the fields' decoded types. The Encoded form mirrors the field schemas' encoded types. Declared fields may be inherited and are copied to own properties in the output. The __proto__ field is accepted only when it is an own property. Parsing does not guarantee that output keys retain their input order.

Example (Defining a basic struct)

import { Schema } from "effect"
const Person = Schema.Struct({
name: Schema.String,
age: Schema.Number,
email: Schema.optionalKey(Schema.String)
})
// { readonly name: string; readonly age: number; readonly email?: string }
type Person = typeof Person.Type
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }

@category ― constructors

@since ― 3.10.0

Struct
({
city: Schema.String
city
:
import Schema
Schema
.
const String: Schema.String

Type-level representation of

String

.

Schema for string values. Validates that the input is typeof "string".

@category ― models

@since ― 4.0.0

@category ― schemas

@since ― 4.0.0

String
,
days: Schema.Int
days
:
import Schema
Schema
.
const Int: Schema.Int

Type-level representation of

Int

.

Schema for integers, rejecting NaN, Infinity, and -Infinity.

@category ― models

@since ― 3.10.0

@category ― schemas

@since ― 3.10.0

Int
.
BottomWithoutNew<number, number, never, never, Number, Number, number, number, readonly [], number, "readonly", "required", "no-default", "readonly", "required">.check(checks_0: Check<number>, ...checks: Check<number>[]): Schema.Int
check
(
import Schema
Schema
.
const isGreaterThan: (exclusiveMinimum: number, annotations?: Schema.Annotations.Filter) => Filter<number>

Validates that a number is greater than the specified value (exclusive).

Details

JSON Schema:

This check corresponds to the exclusiveMinimum constraint in JSON Schema.

Arbitrary:

During arbitrary generation, this applies an exclusiveMinimum constraint to ensure generated numbers are greater than the specified value.

@category ― validation

@since ― 4.0.0

isGreaterThan
(0)) }),
DefinitionOptions<Struct<{ readonly city: String; readonly days: Int; }>, Struct<{ readonly itinerary: $Array<String>; }>, ({ city, days }: { readonly city: string; readonly days: number; }) => string, Toolkit<...>, undefined, undefined, undefined>.output: Schema.Struct<{
readonly itinerary: Schema.$Array<Schema.String>;
}>
output
:
import Schema
Schema
.
function Struct<{
readonly itinerary: Schema.$Array<Schema.String>;
}>(fields: {
readonly itinerary: Schema.$Array<Schema.String>;
}): Schema.Struct<{
readonly itinerary: Schema.$Array<Schema.String>;
}>

Defines a struct schema from a map of field schemas.

Details

Each field value is a schema. Use

optionalKey

or

optional

to mark fields as optional, and

mutableKey

to mark them as mutable.

The resulting schema's Type is a readonly object type with the fields' decoded types. The Encoded form mirrors the field schemas' encoded types. Declared fields may be inherited and are copied to own properties in the output. The __proto__ field is accepted only when it is an own property. Parsing does not guarantee that output keys retain their input order.

Example (Defining a basic struct)

import { Schema } from "effect"
const Person = Schema.Struct({
name: Schema.String,
age: Schema.Number,
email: Schema.optionalKey(Schema.String)
})
// { readonly name: string; readonly age: number; readonly email?: string }
type Person = typeof Person.Type
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }

@category ― constructors

@since ― 3.10.0

Struct
({
itinerary: Schema.$Array<Schema.String>
itinerary
:
import Schema
Schema
.
Array<Schema.String>(self: Schema.String): Schema.$Array<Schema.String>
export Array

Defines a ReadonlyArray schema for a given element schema.

Example (Defining an array of strings)

import { Schema } from "effect"
const schema = Schema.Array(Schema.String)
Schema.decodeUnknownSync(schema)(["a", "b", "c"]) // => ["a", "b", "c"]

@category ― constructors

@since ― 4.0.0

Array
(
import Schema
Schema
.
const String: Schema.String

Type-level representation of

String

.

Schema for string values. Validates that the input is typeof "string".

@category ― models

@since ― 4.0.0

@category ― schemas

@since ― 4.0.0

String
) }),
DefinitionOptions<Struct<{ readonly city: String; readonly days: Int; }>, Struct<{ readonly itinerary: $Array<String>; }>, ({ city, days }: { readonly city: string; readonly days: number; }) => string, Toolkit<...>, undefined, undefined, undefined>.instructions: ({ city, days }: {
readonly city: string;
readonly days: number;
}) => string
instructions
: ({
city: string
city
,
days: number
days
}) =>
`Find activities with search_activities, then plan ${
days: number
days
} days in ${
city: string
city
}.`,
DefinitionOptions<Struct<{ readonly city: String; readonly days: Int; }>, Struct<{ readonly itinerary: $Array<String>; }>, ({ city, days }: { readonly city: string; readonly days: number; }) => string, Toolkit<...>, undefined, undefined, undefined>.toolkit: Toolkit<{
readonly search_activities: Tool<"search_activities", {
readonly parameters: Schema.Struct<{
readonly city: Schema.String;
}>;
readonly success: Schema.$Array<Schema.String>;
readonly failure: Schema.Never;
readonly failureMode: "error";
}, never>;
}>
toolkit
:
const TravelTools: Toolkit<{
readonly search_activities: Tool<"search_activities", {
readonly parameters: Schema.Struct<{
readonly city: Schema.String;
}>;
readonly success: Schema.$Array<Schema.String>;
readonly failure: Schema.Never;
readonly failureMode: "error";
}, never>;
}>
TravelTools
,
DefinitionOptions<Struct<{ readonly city: String; readonly days: Int; }>, Struct<{ readonly itinerary: $Array<String>; }>, ({ city, days }: { readonly city: string; readonly days: number; }) => string, Toolkit<...>, undefined, undefined, undefined>.policy?: Partial<Readonly<Omit<{
readonly runStatus: "appended" | "off";
readonly maxTurns: number;
readonly maxToolCalls: number;
readonly maxDuration: Duration;
readonly toolConcurrency: number;
readonly repeatedFailureLimit: number;
readonly onExhaustion: "final-answer" | "fail";
readonly completionReserveTokens: number;
readonly toolResultBounds: ToolResultBounds;
readonly compaction: CompactionPolicy;
readonly tokenBudget?: number | undefined;
readonly costBudgetMicrousd?: number | undefined;
readonly contextTokenLimit?: number | undefined;
readonly restartOnJoinedInput?: boolean | undefined;
readonly modelRetries?: number | undefined;
}, "runStatus" | ... 5 more ... | "compaction"> & {
...;
}>> | undefined
policy
: {
maxTurns?: number | undefined
maxTurns
: 6,
maxToolCalls?: number | undefined
maxToolCalls
: 10,
maxDuration?: Input | undefined

Finite, positive wall-clock duration accepted in any Effect Duration input form.

maxDuration
: "2 minutes",
},
});
export const
const plan: Effect.Effect<{
readonly threadId: string & Brand<"@effect-agent/core/ThreadId">;
readonly runId: string & Brand<"@effect-agent/core/RunId">;
readonly output: {
readonly itinerary: readonly string[];
};
readonly finishReason: "completed" | "model-stop" | "budget-exhausted";
readonly turns: number;
readonly exhausted?: "tokens" | "tool-calls" | "turns" | undefined;
readonly runDisposition?: Schema.Json | undefined;
readonly usage?: RunTotals | undefined;
readonly delegatedUsage?: RunTotals | undefined;
}, ConfigError | AgentRuntime.AgentRuntimeFailure<...>, never>
plan
=
import AgentRuntime
AgentRuntime
.
run<Agent.Definition<Schema.Struct<{
readonly city: Schema.String;
readonly days: Schema.Int;
}>, Schema.Struct<{
readonly itinerary: Schema.$Array<Schema.String>;
}>, ({ city, days }: {
readonly city: string;
readonly days: number;
}) => string, Toolkit<{
readonly search_activities: Tool<"search_activities", {
readonly parameters: Schema.Struct<{
readonly city: Schema.String;
}>;
readonly success: Schema.$Array<Schema.String>;
readonly failure: Schema.Never;
readonly failureMode: "error";
}, never>;
}>, undefined, undefined, undefined> & {
...;
}, never, never>(agent: Agent.Definition<...> & {
...;
}, input: NoInfer<{
...;
}>, options?: RunOptions<...> | undefined): Effect.Effect<...>
export run

Accept schema-encoded input, retaining runtime validation. Use runUnknown for external data.

run
(
const TravelPlanner: Agent.Definition<Schema.Struct<{
readonly city: Schema.String;
readonly days: Schema.Int;
}>, Schema.Struct<{
readonly itinerary: Schema.$Array<Schema.String>;
}>, ({ city, days }: {
readonly city: string;
readonly days: number;
}) => string, Toolkit<{
readonly search_activities: Tool<"search_activities", {
readonly parameters: Schema.Struct<{
readonly city: Schema.String;
}>;
readonly success: Schema.$Array<Schema.String>;
readonly failure: Schema.Never;
readonly failureMode: "error";
}, never>;
}>, undefined, undefined, undefined> & {
...;
}
TravelPlanner
, {
city: string
city
: "Lisbon",
days: number
days
: 2 }).
Pipeable.pipe<Effect.Effect<{
readonly threadId: string & Brand<"@effect-agent/core/ThreadId">;
readonly runId: string & Brand<"@effect-agent/core/RunId">;
readonly output: {
readonly itinerary: readonly string[];
};
readonly finishReason: "completed" | "model-stop" | "budget-exhausted";
readonly turns: number;
readonly exhausted?: "tokens" | "tool-calls" | "turns" | undefined;
readonly runDisposition?: Schema.Json | undefined;
readonly usage?: RunTotals | undefined;
readonly delegatedUsage?: RunTotals | undefined;
}, AgentRuntime.AgentRuntimeFailure<...>, AgentRuntime.AgentRuntimeRequirements<...>>, Effect.Effect<...>, Effect.Effect<...>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<...>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect
Effect
.
const provide: <LanguageModel | ProviderName | ModelName, never, AnthropicClient>(layer: Layer<LanguageModel | ProviderName | ModelName, never, AnthropicClient>, options?: {
readonly local?: boolean | undefined;
} | undefined) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, AnthropicClient | Exclude<R, LanguageModel | ProviderName | ModelName>> (+5 overloads)

Provides dependencies to an effect using layers or a context. Use options.local to build the layer every time; by default, layers are shared between provide calls.

Example (Providing dependencies with a layer)

import { Context, Effect, Layer } from "effect"
interface Database {
readonly query: (sql: string) => Effect.Effect<string>
}
const Database = Context.Service<Database>("Database")
const DatabaseLayer = Layer.succeed(Database)({
query: Effect.fn("Database.query")((sql: string) => Effect.succeed(`Result for: ${sql}`))
})
const program = Effect.gen(function*() {
const db = yield* Database
return yield* db.query("SELECT * FROM users")
})
const provided = Effect.provide(program, DatabaseLayer)
await Effect.runPromise(provided) // => "Result for: SELECT * FROM users"

@category ― providing services

@since ― 2.0.0

provide
(
import AnthropicLanguageModel
AnthropicLanguageModel
.
const model: (model: (string & {}) | AnthropicLanguageModel.Model, config?: Omit<{
readonly model?: string;
readonly cache_control?: {
readonly ttl?: "1h" | "5m";
readonly type: "ephemeral";
} | null;
readonly container?: string | {
readonly id?: string | null;
readonly skills?: readonly {
readonly skill_id: string;
readonly type: "anthropic" | "custom";
readonly version?: string;
}[] | null;
} | null;
readonly context_management?: {
readonly edits?: readonly ({
readonly clear_at_least?: {
readonly type: "input_tokens";
readonly value: number;
} | null;
readonly clear_tool_inputs?: boolean | readonly string[] | null;
readonly exclude_tools?: readonly string[] | null;
readonly keep?: {
readonly type: "tool_uses";
readonly value: number;
};
readonly trigger?: {
readonly type: "input_tokens";
readonly value: number;
} | {
readonly type: "tool_uses";
readonly value: number;
};
readonly type: "clear_tool_uses_20250919";
} | {
readonly keep?: "all" | {
readonly type: "thinking_turns";
readonly value: number;
} | {
readonly type: "all";
};
readonly type: "clear_thinking_20251015";
} | {
readonly instructions?: string | null;
readonly pause_after_compaction?: boolean;
readonly trigger?: {
readonly type: "input_tokens";
readonly value: number;
} | null;
readonly type: "compact_20260112";
})[];
} | null;
... 16 more ...;
readonly strictJsonSchema?: boolean | undefined;
}, "model">) => Model<"anthropic", LanguageModel, AnthropicClient>

Creates an Anthropic model descriptor that can be provided with Effect.provide.

When to use

Use when you want an Anthropic Claude model value that carries provider and model metadata and can be supplied directly to an Effect program.

@see ― layer for creating a LanguageModel.LanguageModel layer directly

@see ― make for constructing the language model service effectfully

@stability ― unstable

@category ― constructors

@since ― 4.0.0

model
("claude-sonnet-5")),
import Effect
Effect
.
const provide: <Handler<"search_activities"> | ThreadHistory | Store | SubagentReservations | AnthropicClient, ConfigError, never>(layer: Layer<Handler<"search_activities"> | ThreadHistory | Store | SubagentReservations | AnthropicClient, ConfigError, never>, options?: {
readonly local?: boolean | undefined;
} | undefined) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<...> (+5 overloads)

Provides dependencies to an effect using layers or a context. Use options.local to build the layer every time; by default, layers are shared between provide calls.

Example (Providing dependencies with a layer)

import { Context, Effect, Layer } from "effect"
interface Database {
readonly query: (sql: string) => Effect.Effect<string>
}
const Database = Context.Service<Database>("Database")
const DatabaseLayer = Layer.succeed(Database)({
query: Effect.fn("Database.query")((sql: string) => Effect.succeed(`Result for: ${sql}`))
})
const program = Effect.gen(function*() {
const db = yield* Database
return yield* db.query("SELECT * FROM users")
})
const provided = Effect.provide(program, DatabaseLayer)
await Effect.runPromise(provided) // => "Result for: SELECT * FROM users"

@category ― providing services

@since ― 2.0.0

provide
(
const AppLive: Layer<Handler<"search_activities"> | ThreadHistory | Store | SubagentReservations | AnthropicClient, ConfigError, never>
AppLive
),
);
tools.ts
import {
import Effect
Effect
,
import Schema
Schema
} from "effect";
import {
import Tool
Tool
,
import Toolkit
Toolkit
} from "effect/ai";
const
const SearchActivities: Tool.Tool<"search_activities", {
readonly parameters: Schema.Struct<{
readonly city: Schema.String;
}>;
readonly success: Schema.$Array<Schema.String>;
readonly failure: Schema.Never;
readonly failureMode: "error";
}, never>
SearchActivities
=
import Tool
Tool
.
const make: <"search_activities", Schema.Struct<{
readonly city: Schema.String;
}>, Schema.$Array<Schema.String>, Schema.Never, undefined, []>(name: "search_activities", options?: {
readonly description?: string | undefined;
readonly parameters?: Schema.Struct<{
readonly city: Schema.String;
}> | undefined;
readonly success?: Schema.$Array<Schema.String> | undefined;
readonly failure?: Schema.Never | undefined;
readonly failureMode?: undefined;
readonly dependencies?: [] | undefined;
readonly needsApproval?: Tool.NeedsApproval<...> | undefined;
} | undefined) => Tool.Tool<...>

Creates a user-defined tool with the specified name and configuration.

Details

This is the primary constructor for creating custom tools that AI models can call. The tool definition includes parameter validation, success/failure schemas, and optional service dependencies.

If a tool accepts no parameters but still needs an explicit empty object schema, use

EmptyParams

.

Example (Creating a tool without parameters)

import { Schema } from "effect"
import { Tool } from "effect/ai"
// Simple tool with no parameters
const GetCurrentTime = Tool.make("GetCurrentTime", {
description: "Returns the current timestamp",
success: Schema.Number
})
GetCurrentTime.name // => "GetCurrentTime"

@stability ― unstable

@category ― constructors

@since ― 4.0.0

make
("search_activities", {
description?: string | undefined

An optional description explaining what the tool does.

description
: "Find activities in a city.",
parameters?: Schema.Struct<{
readonly city: Schema.String;
}> | undefined

Schema defining the parameters this tool accepts.

parameters
:
import Schema
Schema
.
function Struct<{
readonly city: Schema.String;
}>(fields: {
readonly city: Schema.String;
}): Schema.Struct<{
readonly city: Schema.String;
}>

Defines a struct schema from a map of field schemas.

Details

Each field value is a schema. Use

optionalKey

or

optional

to mark fields as optional, and

mutableKey

to mark them as mutable.

The resulting schema's Type is a readonly object type with the fields' decoded types. The Encoded form mirrors the field schemas' encoded types. Declared fields may be inherited and are copied to own properties in the output. The __proto__ field is accepted only when it is an own property. Parsing does not guarantee that output keys retain their input order.

Example (Defining a basic struct)

import { Schema } from "effect"
const Person = Schema.Struct({
name: Schema.String,
age: Schema.Number,
email: Schema.optionalKey(Schema.String)
})
// { readonly name: string; readonly age: number; readonly email?: string }
type Person = typeof Person.Type
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }

@category ― constructors

@since ― 3.10.0

Struct
({
city: Schema.String
city
:
import Schema
Schema
.
const String: Schema.String

Type-level representation of

String

.

Schema for string values. Validates that the input is typeof "string".

@category ― models

@since ― 4.0.0

@category ― schemas

@since ― 4.0.0

String
}),
success?: Schema.$Array<Schema.String> | undefined

Schema for successful tool execution results.

success
:
import Schema
Schema
.
Array<Schema.String>(self: Schema.String): Schema.$Array<Schema.String>
export Array

Defines a ReadonlyArray schema for a given element schema.

Example (Defining an array of strings)

import { Schema } from "effect"
const schema = Schema.Array(Schema.String)
Schema.decodeUnknownSync(schema)(["a", "b", "c"]) // => ["a", "b", "c"]

@category ― constructors

@since ― 4.0.0

Array
(
import Schema
Schema
.
const String: Schema.String

Type-level representation of

String

.

Schema for string values. Validates that the input is typeof "string".

@category ― models

@since ― 4.0.0

@category ― schemas

@since ― 4.0.0

String
),
});
export const
const TravelTools: Toolkit.Toolkit<{
readonly search_activities: Tool.Tool<"search_activities", {
readonly parameters: Schema.Struct<{
readonly city: Schema.String;
}>;
readonly success: Schema.$Array<Schema.String>;
readonly failure: Schema.Never;
readonly failureMode: "error";
}, never>;
}>
TravelTools
=
import Toolkit
Toolkit
.
const make: <[Tool.Tool<"search_activities", {
readonly parameters: Schema.Struct<{
readonly city: Schema.String;
}>;
readonly success: Schema.$Array<Schema.String>;
readonly failure: Schema.Never;
readonly failureMode: "error";
}, never>]>(tools_0: Tool.Tool<"search_activities", {
readonly parameters: Schema.Struct<{
readonly city: Schema.String;
}>;
readonly success: Schema.$Array<Schema.String>;
readonly failure: Schema.Never;
readonly failureMode: "error";
}, never>) => Toolkit.Toolkit<...>

Creates a new toolkit from the specified tools.

Details

This is the primary constructor for creating toolkits. It accepts multiple tools and organizes them into a toolkit that can be provided to AI language models.

Example (Creating a toolkit)

import { Effect, Schema } from "effect"
import { Tool, Toolkit } from "effect/ai"
const GetCurrentTime = Tool.make("GetCurrentTime", {
description: "Get the current timestamp",
success: Schema.Number
})
const GetWeather = Tool.make("get_weather", {
description: "Get weather information",
parameters: Schema.Struct({ location: Schema.String }),
success: Schema.Struct({
temperature: Schema.Number,
condition: Schema.String
})
})
const toolkit = Toolkit.make(GetCurrentTime, GetWeather)
const ready = toolkit.pipe(Effect.provide(toolkit.toLayer({
GetCurrentTime: () => Effect.succeed(0),
get_weather: () => Effect.succeed({ temperature: 20, condition: "clear" })
})))
Object.keys((await Effect.runPromise(ready)).tools) // => ["GetCurrentTime", "get_weather"]

@stability ― unstable

@category ― constructors

@since ― 4.0.0

make
(
const SearchActivities: Tool.Tool<"search_activities", {
readonly parameters: Schema.Struct<{
readonly city: Schema.String;
}>;
readonly success: Schema.$Array<Schema.String>;
readonly failure: Schema.Never;
readonly failureMode: "error";
}, never>
SearchActivities
);
// Sample data. A real handler can query your database or a travel API.
const
const activities: {
city: string;
name: string;
}[]
activities
= [
{
city: string
city
: "Lisbon",
name: string
name
: "Riverside walk" },
{
city: string
city
: "Lisbon",
name: string
name
: "Food market" },
{
city: string
city
: "Lisbon",
name: string
name
: "City museum" },
];
export const
const TravelToolsLive: Layer<Tool.Handler<"search_activities">, never, never>
TravelToolsLive
=
const TravelTools: Toolkit.Toolkit<{
readonly search_activities: Tool.Tool<"search_activities", {
readonly parameters: Schema.Struct<{
readonly city: Schema.String;
}>;
readonly success: Schema.$Array<Schema.String>;
readonly failure: Schema.Never;
readonly failureMode: "error";
}, never>;
}>
TravelTools
.
Toolkit<{ readonly search_activities: Tool<"search_activities", { readonly parameters: Struct<{ readonly city: String; }>; readonly success: $Array<String>; readonly failure: Never; readonly failureMode: "error"; }, never>; }>.toLayer<{
search_activities: ({ city }: {
readonly city: string;
}) => Effect.Effect<string[], never, never>;
}, never, never>(build: {
search_activities: ({ city }: {
readonly city: string;
}) => Effect.Effect<string[], never, never>;
} | Effect.Effect<{
search_activities: ({ city }: {
readonly city: string;
}) => Effect.Effect<string[], never, never>;
}, never, never>): Layer<Tool.Handler<"search_activities">, never, never>

Converts a toolkit into a Layer containing handlers for each tool in the toolkit.

toLayer
({
search_activities: ({ city }: {
readonly city: string;
}) => Effect.Effect<string[], never, never>
search_activities
: ({
city: string
city
}) =>
import Effect
Effect
.
const succeed: <string[]>(value: string[]) => Effect.Effect<string[], never, never>

Creates an Effect that always succeeds with a given value.

When to use

Use when an effect should complete successfully with a specific value without any errors or external dependencies.

Example (Creating a successful effect)

import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)
Effect.runSync(success) // => 42

@see ― fail to create an effect that represents a failure.

@category ― constructors

@since ― 2.0.0

succeed
(
const activities: {
city: string;
name: string;
}[]
activities
.
Array<{ city: string; name: string; }>.filter(predicate: (value: {
city: string;
name: string;
}, index: number, array: {
city: string;
name: string;
}[]) => unknown, thisArg?: any): {
city: string;
name: string;
}[] (+1 overload)

Returns the elements of an array that meet the condition specified in a callback function.

@param ― predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.

@param ― thisArg An object to which the this keyword can refer in the predicate function. If thisArg is omitted, undefined is used as the this value.

filter
((
a: {
city: string;
name: string;
}
a
) =>
a: {
city: string;
name: string;
}
a
.
city: string
city
===
city: string
city
).
Array<{ city: string; name: string; }>.map<string>(callbackfn: (value: {
city: string;
name: string;
}, index: number, array: {
city: string;
name: string;
}[]) => string, thisArg?: any): string[]

Calls a defined callback function on each element of an array, and returns an array that contains the results.

@param ― callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.

@param ― thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.

map
((
a: {
city: string;
name: string;
}
a
) =>
a: {
city: string;
name: string;
}
a
.
name: string
name
)),
});
setup.ts
import {
import AnthropicClient
AnthropicClient
} from "@effect/ai-anthropic";
import {
import InMemory
InMemory
} from "@yielded/agent";
import {
import Config
Config
,
import Layer
Layer
} from "effect";
import {
import FetchHttpClient
FetchHttpClient
} from "effect/http";
import {
const TravelToolsLive: Layer.Layer<Handler<"search_activities">, never, never>
TravelToolsLive
} from "./tools";
const
const AnthropicLive: Layer.Layer<AnthropicClient.AnthropicClient, Config.ConfigError, never>
AnthropicLive
=
import AnthropicClient
AnthropicClient
.
const layerConfig: (options?: {
readonly apiKey?: Config.Config<Redacted<string> | undefined> | undefined;
readonly apiUrl?: Config.Config<string> | undefined;
readonly apiVersion?: Config.Config<string> | undefined;
readonly transformClient?: ((client: HttpClient) => HttpClient) | undefined;
}) => Layer.Layer<AnthropicClient.AnthropicClient, Config.ConfigError, HttpClient>

Creates a layer for the Anthropic client, loading the requisite configuration via Effect's Config module.

When to use

Use when you want to provide the Anthropic client as a Layer with configuration loaded from Effect's Config module, such as from environment variables or a secrets provider.

@see ― layer for providing the client from explicit options instead of Config

@see ― make for constructing the client service effectfully

@stability ― unstable

@category ― layers

@since ― 4.0.0

layerConfig
({
apiKey?: Config.Config<Redacted<string> | undefined> | undefined

The Anthropic API key for authentication. Requests are made without authentication when this is omitted, which is useful for proxied setups or testing.

apiKey
:
import Config
Config
.
function Redacted(name?: string): Config.Config<import("effect/Redacted").Redacted<string>>

Creates a config for a redacted string value. The parsed result is wrapped in a Redacted container that hides the value from logs and toString.

When to use

Use to read secret string settings that should not be exposed in logs or string output.

Details

Shortcut for Config.schema(Schema.Redacted(Schema.String), name).

Example (Reading a secret)

import { Config, ConfigProvider, Effect } from "effect"
const program = Config.Redacted("API_KEY").pipe(Effect.map(String))
const provider = ConfigProvider.fromEnv({
env: {
API_KEY: "sk-1234567890abcdef"
}
})
Effect.runSync(
program.pipe(Effect.provideService(ConfigProvider.ConfigProvider, provider))
) // => "<redacted>"

@see ― String for non-secret string settings

@category ― constructors

@since ― 2.0.0

Redacted
("ANTHROPIC_API_KEY"),
}).
Pipeable.pipe<Layer.Layer<AnthropicClient.AnthropicClient, Config.ConfigError, HttpClient>, Layer.Layer<AnthropicClient.AnthropicClient, Config.ConfigError, never>>(this: Layer.Layer<AnthropicClient.AnthropicClient, Config.ConfigError, HttpClient>, ab: (_: Layer.Layer<AnthropicClient.AnthropicClient, Config.ConfigError, HttpClient>) => Layer.Layer<AnthropicClient.AnthropicClient, Config.ConfigError, never>): Layer.Layer<...> (+21 overloads)
pipe
(
import Layer
Layer
.
const provide: <never, never, HttpClient>(that: Layer.Layer<HttpClient, never, never>) => <RIn2, E2, ROut2>(self: Layer.Layer<ROut2, E2, RIn2>) => Layer.Layer<ROut2, E2, Exclude<RIn2, HttpClient>> (+3 overloads)

Feeds the output services of the dependency layer into the requirements of this layer, returning a layer that only provides the services from this layer.

When to use

Use when you need to hide an implementation dependency layer from callers.

Details

In serviceLayer.pipe(Layer.provide(dependencyLayer)), the dependency layer is built first and is used to satisfy the requirements of serviceLayer.

Example (Providing layer dependencies)

import { Context, Effect, Layer } from "effect"
class Database extends Context.Service<Database, {
readonly query: (sql: string) => Effect.Effect<string>
}>()("Database") {}
class UserService extends Context.Service<UserService, {
readonly getUser: (id: string) => Effect.Effect<{
id: string
name: string
}>
}>()("UserService") {}
class Logger extends Context.Service<Logger, {
readonly log: (msg: string) => Effect.Effect<void>
}>()("Logger") {}
// Create dependency layers
const databaseLayer = Layer.succeed(Database, {
query: Effect.fn("Database.query")((sql: string) => Effect.succeed(`DB: ${sql}`))
})
const logs: Array<string> = []
const loggerLayer = Layer.succeed(Logger, {
log: Effect.fn("Logger.log")((msg: string) => Effect.sync(() => logs.push(`[LOG] ${msg}`)))
})
// UserService depends on Database and Logger
const userServiceLayer = Layer.effect(UserService, Effect.gen(function*() {
const database = yield* Database
const logger = yield* Logger
return {
getUser: Effect.fn("UserService.getUser")(function*(id: string) {
yield* logger.log(`Looking up user ${id}`)
const result = yield* database.query(
`SELECT * FROM users WHERE id = ${id}`
)
return { id, name: result }
})
}
}))
// Provide dependencies to UserService layer
const userServiceWithDependencies = userServiceLayer.pipe(
Layer.provide(Layer.mergeAll(databaseLayer, loggerLayer))
)
// Now UserService layer has no dependencies
const program = Effect.gen(function*() {
const userService = yield* UserService
return yield* userService.getUser("123")
}).pipe(
Effect.provide(userServiceWithDependencies)
)
Effect.runSync(program) // => { id: "123", name: "DB: SELECT * FROM users WHERE id = 123" }
logs // => ["[LOG] Looking up user 123"]

@see ― provideMerge for retaining the dependency services

@category ― providing services

@since ― 2.0.0

provide
(
import FetchHttpClient
FetchHttpClient
.
const layer: Layer.Layer<HttpClient, never, never>

Layer that provides an HttpClient implementation backed by the configured Fetch function.

When to use

Use when an Effect program should execute HttpClient requests through the platform fetch implementation, especially in browser, edge, or Node.js runtimes with globalThis.fetch.

Details

The layer uses the current Fetch reference and optional RequestInit service for each request. Request-specific method, headers, body, and abort signal are supplied by the client and override matching RequestInit fields.

Gotchas

Fetch behavior comes from the runtime's implementation, so CORS, cookies, redirects, abort handling, and streaming support can vary by platform. Stream request bodies are sent as Web streams with duplex: "half", and any content-length header is removed before calling fetch.

@see ― Fetch for supplying the fetch implementation used by this layer

@see ― RequestInit for default RequestInit options applied before request-specific fields

@stability ― unstable

@category ― layers

@since ― 4.0.0

layer
));
export const
const AppLive: Layer.Layer<Handler<"search_activities"> | AnthropicClient.AnthropicClient | ThreadHistory | Store | SubagentReservations, Config.ConfigError, never>
AppLive
=
import Layer
Layer
.
const mergeAll: <[Layer.Layer<Handler<"search_activities">, never, never>, Layer.Layer<ThreadHistory | Store | SubagentReservations, never, never>, Layer.Layer<AnthropicClient.AnthropicClient, Config.ConfigError, never>]>(layers_0: Layer.Layer<Handler<"search_activities">, never, never>, layers_1: Layer.Layer<ThreadHistory | Store | SubagentReservations, never, never>, layers_2: Layer.Layer<...>) => Layer.Layer<...>

Combines all the provided layers concurrently, creating a new layer with merged input, error, and output types.

When to use

Use when you need to combine multiple independent layers.

Details

All layers are built concurrently, and their outputs are merged into a single layer.

If multiple merged layers depend on the same layer value, that dependency is shared by default. Reuse a named layer value when you want services to share the same resource, such as one database pool.

Example (Merging independent layers)

import { Context, Effect, Layer } from "effect"
class Database extends Context.Service<Database, {
readonly query: (sql: string) => Effect.Effect<string>
}>()("Database") {}
class Logger extends Context.Service<Logger, {
readonly log: (msg: string) => Effect.Effect<void>
}>()("Logger") {}
const dbLayer = Layer.succeed(Database, {
query: Effect.fn("Database.query")((sql: string) => Effect.succeed("result"))
})
const logs: Array<string> = []
const loggerLayer = Layer.succeed(Logger, {
log: Effect.fn("Logger.log")((msg: string) => Effect.sync(() => logs.push(msg)))
})
const mergedLayer = Layer.mergeAll(dbLayer, loggerLayer)
const program = Logger.use((logger) => logger.log("ready"))
Effect.runSync(Effect.provide(program, mergedLayer))
logs // => ["ready"]

@see ― merge for merging one layer with another layer or array

@category ― zipping

@since ― 2.0.0

mergeAll
(
const TravelToolsLive: Layer.Layer<Handler<"search_activities">, never, never>
TravelToolsLive
,
import InMemory
InMemory
.
const layer: Layer.Layer<ThreadHistory | Store | SubagentReservations, never, never>

Run agents and attached subagents with in-memory conversation history. Provide once around the parent program and all child handler Layers so siblings share history and one reservation ledger. Reuse a Thread ID to continue a conversation. Conversations can span any number of Runs within the store's capacity limits. Use scoped for disposable request workflows within this shared store. Each independent Layer build owns fresh state; state is released when its Scope closes. Process loss loses history and active execution; this Layer provides no crash recovery.

Models, tool handlers, and provider clients remain application-supplied. Default IDs need no Layer; enclosing ID and context-preparation overrides are preserved. For storage-backed history, provide PersistentHistory.layer and a shared SubagentReservationsMemoryLive instead. Durable hosts own their own assembly.

layer
,
const AnthropicLive: Layer.Layer<AnthropicClient.AnthropicClient, Config.ConfigError, never>
AnthropicLive
);