Skip to content

Conversation

@IMax153
Copy link
Member

@IMax153 IMax153 commented Oct 7, 2025

Type

  • Refactor
  • Feature
  • Bug Fix
  • Optimization
  • Documentation Update

Description

This PR walks back a few of the changes made in #5614.

Specifically, the encoding of tool call results as an Either / EitherEncoded has been removed and is replaced by encoding the tool call success / failure directly into the result property.

To allow type-safe discrimination between a tool call result which was a success vs. one that was a failure, an isFailure property has also been added to the "tool-result" part. If isFailure is true, then the tool call handler result was an error.

import * as AnthropicClient from "@effect/ai-anthropic/AnthropicClient"
import * as AnthropicLanguageModel from "@effect/ai-anthropic/AnthropicLanguageModel"
import * as LanguageModel from "@effect/ai/LanguageModel"
import * as Tool from "@effect/ai/Tool"
import * as Toolkit from "@effect/ai/Toolkit"
import * as NodeHttpClient from "@effect/platform-node/NodeHttpClient"
import { Config, Effect, Layer, Schema, Stream } from "effect"

const Claude = AnthropicLanguageModel.model("claude-4-sonnet-20250514")

const MyTool = Tool.make("MyTool", {
  description: "An example of a tool with success and failure types",
  failureMode: "return", // Return errors in the response
  parameters: { bar: Schema.Number },
  success: Schema.Number,
  failure: Schema.Struct({ reason: Schema.Literal("reason-1", "reason-2") })
})

const MyToolkit = Toolkit.make(MyTool)

const MyToolkitLayer = MyToolkit.toLayer({
  MyTool: () => Effect.succeed(42)
})

const program = LanguageModel.streamText({
  prompt: "Tell me about the meaning of life",
  toolkit: MyToolkit
}).pipe(
  Stream.runForEach((part) => {
    if (part.type === "tool-result" && part.name === "MyTool") {
      // The `isFailure` property can be used to discriminate whether the result
      // of a tool call is a success or a failure
      if (part.isFailure) {
        part.result
        //   ^? { readonly reason: "reason-1" | "reason-2"; }
      } else {
        part.result
        //   ^? number
      }
    }
    return Effect.void
  }),
  Effect.provide(Claude)
)

const Anthropic = AnthropicClient.layerConfig({
  apiKey: Config.redacted("ANTHROPIC_API_KEY")
}).pipe(Layer.provide(NodeHttpClient.layerUndici))

program.pipe(
  Effect.provide([Anthropic, MyToolkitLayer]),
  Effect.runPromise
)

Related

  • Related Issue #
  • Closes #

@github-project-automation github-project-automation bot moved this to Discussion Ongoing in PR Backlog Oct 7, 2025
@changeset-bot
Copy link

changeset-bot bot commented Oct 7, 2025

🦋 Changeset detected

Latest commit: 4ed4557

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 6 packages
Name Type
@effect/ai Patch
@effect/ai-amazon-bedrock Patch
@effect/ai-anthropic Patch
@effect/ai-google Patch
@effect/ai-openai Patch
@effect/ai-openrouter Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@IMax153 IMax153 merged commit 4c3bdfb into main Oct 7, 2025
11 checks passed
@IMax153 IMax153 deleted the fix/tool-call-results branch October 7, 2025 18:26
@github-project-automation github-project-automation bot moved this from Discussion Ongoing to Done in PR Backlog Oct 7, 2025
@github-actions github-actions bot mentioned this pull request Oct 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

2 participants