@charcoalhq/ai-sdk
v0.1.0
Published
Charcoal tools for the Vercel AI SDK
Downloads
29
Maintainers
Readme
@charcoalhq/ai-sdk
Charcoal tools for the Vercel AI SDK.
Give your agent one tool and let Charcoal handle planning, multi-hop retrieval, and citation over your corpus.
Installation
npm install @charcoalhq/ai-sdk @charcoalhq/sdk ai zodUsage
Set CHARCOAL_API_KEY in your environment. The package ships two entry points — a zero-config tool and a factory for the common case where you want to bake defaults in code.
searchTool
Your agent's model supplies namespace, objective, and context on every call.
import { generateText } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { searchTool } from "@charcoalhq/ai-sdk";
const { text } = await generateText({
model: anthropic("claude-sonnet-4-6"),
tools: { search: searchTool },
prompt:
"In the `contracts` namespace, find every MSA with auto-renewal longer than 24 months.",
});createSearchTool
Bake the namespace, auth, filters, or description into the tool. Anything set here is removed from the input schema your agent's model sees, so it only reasons about objective and context.
import { createSearchTool } from "@charcoalhq/ai-sdk";
const contractSearch = createSearchTool({
namespace: "contracts",
filters: { status: "active" },
description: "Search active vendor contracts.",
});
const { text } = await generateText({
model: anthropic("claude-sonnet-4-6"),
tools: { search: contractSearch },
prompt: "Find every MSA with auto-renewal longer than 24 months.",
});Under the hood, each tool call hits client.namespaces.search.create(namespace, { objective, context, filters? }) on @charcoalhq/sdk and returns a synthesized answer with cited excerpts.
Streaming
Both searchTool and createSearchTool stream by default. Under the hood, execute is an async generator that yields each SearchStreamEvent as it arrives — the AI SDK surfaces intermediate yields (status events) as preliminary tool outputs on the data stream, so your UI sees progress in real time. The final yield is the session_result event, which your agent's model consumes as the tool result. Error events are thrown by the underlying SDK.
// UI code consuming the AI SDK's data stream — no extra plumbing needed.
const { textStream, fullStream } = streamText({
model: anthropic("claude-sonnet-4-6"),
tools: { search: createSearchTool({ namespace: "contracts" }) },
prompt: "...",
});
for await (const part of fullStream) {
if (part.type === "tool-output-available") {
// part.output is a SearchStreamEvent — 'status', 'session_result', etc.
}
}Set stream: false to opt into a single-shot non-streaming call that yields just the synthesized SearchResponse.
SearchStreamEvent is re-exported from @charcoalhq/sdk, so you get proper narrowing on event.type.
CreateSearchToolOptions
type CreateSearchToolOptions = {
// Namespace to search. If set, removed from the input schema your agent's model sees.
namespace?: string;
// Defaults to process.env.CHARCOAL_API_KEY.
apiKey?: string;
// Pre-built Charcoal client (takes precedence over apiKey and baseUrl).
client?: Charcoal;
// Filters applied to every search call.
filters?: SearchCreateParams["filters"];
// Override the tool description shown to your agent's model.
description?: string;
// Stream SSE events through execute as an async generator. Defaults to true.
stream?: boolean;
// Override the API base URL. Defaults to https://api.withcharcoal.com.
baseUrl?: string;
};See docs.withcharcoal.com for the full search API, filter syntax, and schema reference.
Development
pnpm install
cp .env.example .env # add your CHARCOAL_API_KEY and CHARCOAL_NAMESPACE
pnpm test # invokes the tool against a real namespace (streaming)
pnpm build # emits dist/License
MIT
