Skip to content

Agents & stream requirements

Binding a toolkit on the agent layer

Pass toolkit when building the agent layer — not on every stream call:

ts
const agentLayer = MastraAgent.layer({
  id: "docs-agent",
  name: "Docs Agent",
  instructions: "Use search_docs when needed.",
  model: "openai/gpt-4o",
  toolkit,
})

Agent.stream and Agent.generate register the toolkit's Mastra tools on the request toolset automatically.

Handler requirements in R

When a toolkit is bound, stream/generate expose tool requirements in R:

  • Server tools — require ToolHandlers from toolkit.toLayer(Effect.fn(...)). Handler deps (ApiKey, etc.) appear in the layer's R and must be provided per run.
  • Client tools — do not add a server handler layer. They register Mastra stubs and throw ClientToolRequiredError if the server execute path is hit. Fulfillment happens in the browser via Assistant UI.
ts
const handlersLayer = toolkit.toLayer(
  Effect.fn(function* () {
    return {
      search_docs: Effect.fn(function* ({ query }) {
        const api = yield* ApiKey
        return `(${api.token}) results for ${query}`
      }),
    }
  })(),
)

await Effect.runPromise(
  Agent.stream("Find Effect Layer docs").pipe(
    Effect.provide(Layer.merge(agentLayer, handlersLayer)),
    Effect.provide(Layer.succeed(ApiKey, { token: process.env.API_KEY! })),
  ),
)

No separate UI handler layer is needed on the server for requiredClient tools.

Agent exports

ExportDescription
MastraAgent.layer(config)Build agent; pass toolkit to bind tools
Agent.generate(messages, options?)Full response
Agent.stream(messages, options?)Stream chunks as Effect Stream

Memory & stream utilities

See API overview for Memory.* and stream helpers (fromMastraOutput, runCollect, etc.).