# Durable Agents Durable agent execution - Package: @bijectionhq/durable-agents - Category: AI & Agents - Status: Reference - License: Apache-2.0 - Bijection source (repository access required): https://github.com/bijectionhq/durable-agents/tree/6322213b09dc69d3c9c82ab465ca30fbcb7d2070 - Upstream: https://github.com/ziegfried/convex-durable-agents/tree/85959879a9d61a5b85b1eb543531606277e071b4 - Documentation: https://docs.bijection.com/components/using - Directory: https://bijection.com/components/durable-agents ## Get the source Bijection repository access is required. Request access at https://bijection.com/contact. ```sh git clone https://github.com/bijectionhq/durable-agents.git cd durable-agents git checkout 6322213b09dc69d3c9c82ab465ca30fbcb7d2070 ``` ## Before using this component Read the package README at the recorded revision for setup, dependencies, and API examples. Upstream documentation describes the original package and may differ from the Bijection adaptation. This is a source candidate for evaluation. Catalog inclusion does not establish npm availability or runtime qualification. Check compatibility with your SDK and deployment before adoption. External providers run their own compute. ## Upstream package documentation Recorded 2026-10-23. This describes convex-durable-agents; check the Bijection adaptation separately. This component provides durable AI agents that can run indefinitely and survive server restarts or failures. Built on AI SDK v6, it executes agent tool loops asynchronously to avoid Convex action time limits while maintaining persistent streaming and automatic retries. Agents can call external APIs through Convex actions and optionally route execution through workpools for parallelism control. ### Use cases - **Long-running AI workflows** that need to survive dev server restarts and production failures without losing conversation state - **AI agents with external API calls** that require automatic retry logic and durable execution when tools fail or timeout - **Multi-step agent tasks** that exceed Convex action time limits by running tool loops asynchronously with persistent state - **Production chatbots** that need real-time streaming with message persistence and the ability to resume interrupted conversations - **Background AI processing** where agents need to continue working even when the user disconnects or the browser closes ### How it works The component wraps AI SDK's `streamText` API with Convex's durable execution model. You define agents using `streamHandlerAction` with your language model and tools, then export a complete API using `defineAgentApi` for public access or `defineInternalAgentApi` for server-only access. Tools are implemented as Convex actions using `createActionTool` for synchronous results or `createAsyncTool` for background processing. The component handles automatic retries with configurable backoff strategies and can route execution through `@convex-dev/workpool` for parallelism control. Real-time streaming works through `streamUpdates` queries that deliver message deltas to React components via the `useAgentChat` hook. Thread state persists across failures, allowing agents to resume exactly where they left off using `resumeThread`. Authorization callbacks protect thread access, and the component maintains full conversation history with support for both user messages and tool execution results. ### Upstream README # Durable Agents Component for Convex A Convex component for building durable AI agents with an async tool loop. The goal of this component is to provide a way to build AI agents that can run indefinitely and survive failures and restarts. It provides some of the functionality of the [Convex Agents Component](https://www.convex.dev/components/agent) (such as persistent streaming), while deliberately leaving out some of the more advanced features (context management, RAG, rate limiting, etc.). The component is built on top of the [AI SDK v6](https://ai-sdk.dev/) and aims to expose its full `streamText` API with persistence and durable execution. **Note:** This component is still in early development and is not yet ready for production use. The API will very likely change before a first stable release. ## Features - **Async Execution**: Agent tool loop is executed asynchronously to avoid time limits of convex actions - **Tool Execution**: via convex actions - support for both sync and async tools - **Automatic Retries**: Failed tool calls are automatically retried (opt-in) - **Durable Execution**: Agent tool loops survive crashes and dev server restarts - **Workpool Support**: Optionally route agent and tool execution through `@convex-dev/workpool` for parallelism control ## Installation ```bash npm install convex-durable-agents ai zod ``` ## Quick Start ### 1. Configure the Component Create a `convex.config.ts` file in your app's `convex/` folder: ```ts // convex/convex.config.ts import { defineApp } from "convex/server"; import durableAgents from "convex-durable-agents/convex.config.js"; const app = defineApp(); app.use(durableAgents); export default app; ``` ### 2. Define Your Agent Create a chat handler with your AI model and tools: ```ts // convex/chat.ts import { z } from "zod"; import { components, internal } from "./_generated/api"; import { createActionTool, defineAgentApi, streamHandlerAction } from "convex-durable-agents"; // Define the stream handler with your model and tools export const chatAgentHandler = streamHandlerAction(components.durableAgents, { model: "anthropic/claude-haiku-4.5", system: "You are a helpful AI assistant.", tools: { get_weather: createActionTool({ description: "Get weather for a location", args: z.object({ location: z.string() }), handler: internal.tools.weather.getWeather, retry: { enabled: true, maxAttempts: 5, }, }), }, saveStreamDeltas: true, // Enable real-time streaming }); // Export the agent API (public - callable from clients) export const { createThread, sendMessage, getThread, listMessages, streamUpdates, listThreads, deleteThread, resumeThread, stopThread, addToolResult, addToolError, } = defineAgentApi(components.durableAgents, internal.chat.chatAgentHandler, { // Optional: Add authorization to protect thread access authorizationCallback: async (ctx, threadId) => { // Example: verify the user owns this thread // const identity = await ctx.auth.getUserIdentity(); // if (!identity) throw new Error("Unauthorized"); }, }); ``` #### Using Internal API If you want to restrict the agent API to only be callable from other Convex functions (not directly from clients), use `defineInternalAgentApi` instead: ```ts // convex/chat.ts import { defineInternalAgentApi } from "convex-durable-agents"; // Export internal agent API (only callable from other Convex functions) export const { createThread, sendMessage, getThread, // ... other functions } = defineInternalAgentApi(components.durableAgents, internal.chat.chatAgentHandler); ``` This is useful when you want to: - Add authentication/authorization checks before calling agent functions - Wrap agent functions with additional business logic - Prevent direct client access to the agent API - Run agents in the background You can then create your own public functions that call the internal API: ```ts // convex/myChat.ts import { mutation, query } from "./_generated/server"; import { internal } from "./_generated/api"; import { v } from "convex/values"; // Public wrapper with auth check export const sendMessage = mutation({ args: { threadId: v.string(), prompt: v.string() }, handler: async (ctx, args) => { const identity = await ctx.auth.getUserIdentity(); if (!identity) throw new Error("Not authenticated"); // Call the internal agent API return ctx.runMutation(internal.chat.sendMessage, args); }, }); ``` ### 3. Create Tool Handlers Tools are defined as Convex actions: ```ts // convex/tools/weather.ts import { v } from "convex/values"; import { internalAction } from "../_generated/server"; export const getWeather = internalAction({ args: { location: v.string() }, returns: v.object({ weather: v.string(), temperature: v.number() }), handler: async (_ctx, args) => { // Call your weather API here return { weather: "sunny", temperature: 72 }; }, }); ``` ### 4. Build Your UI Use the React hooks to build your chat interface: ```tsx import { useAgentChat } from "convex-durable-agents/react"; import { api } from "../convex/_generated/api"; function ChatView({ threadId }: { threadId: string }) { const { messages, status, isRunning, sendMessage, stop } = useAgentChat({ listMessages: api.chat.listMessages, streamUpdates: api.chat.streamUpdates, getThread: api.chat.getThread, sendMessage: api.chat.sendMessage, stopThread: api.chat.stopThread, resumeThread: api.chat.resumeThread, threadId, }); return (