@agentskit/adapters

中文文档
0.19.2发布于 2026/10/26MITTypeScriptESM + CJS构建来源已验证近 30 天下载 1.4万

Provider adapters for AgentsKit.

原始使用文档
文档目录25 节
  1. Verified proof
  2. How this fits the ecosystem
  3. Why adapters
  4. Gateway and multimodal transport
  5. Install
  6. Quick example
  7. Embeddings (for RAG)
  8. Features
  9. CLI-backed adapters
  10. exec-text vs exec-json : what each protocol can return
  11. Claude Code
  12. Prompt serialization
  13. LangChain bridge: use any adapter as a LangChain chat model
  14. Stream guarantees
  15. Higher-order adapters
  16. Ecosystem
  17. Testing Adapters
  18. mockAdapter — deterministic responses
  19. recordingAdapter + inMemorySink — capture real calls
  20. replayAdapter — replay captured fixtures
  21. Contributors
  22. License
  23. Docs
  24. Maturity and compatibility
  25. Contributing

@agentskit/adapters

Profile: major-package

AgentsKit

Connect to any LLM provider — and swap between them — without touching your app code.

npm version npm downloads bundle size license stability GitHub stars

Tags: ai · agents · llm · agentskit · openai · anthropic · claude · gemini · chatgpt · ollama · embeddings · providers

Verified proof

How this fits the ecosystem

@agentskit/adapters is the provider layer: swap OpenAI, Anthropic, Gemini, Ollama, local models, and embedding providers without rewriting your agent.

  • AgentsKit: compose it with the other packages in this repo to build agents from small, swappable parts.
  • Registry: look for ready agents and templates that already use this layer at registry.agentskit.io.
  • Playbook: learn the production patterns behind this layer at playbook.agentskit.io.

Docs: package guide · agent handoff

Why adapters

  • Vendor independence — switch from OpenAI to Anthropic to a local Ollama model by changing one line; your hooks, runtime, and tools stay untouched
  • 25 native adapters in the catalog — Anthropic, OpenAI, Gemini, Ollama, DeepSeek, Grok, Kimi, Mistral, Cohere, Together, Groq, Fireworks, OpenRouter, Hugging Face, LM Studio, vLLM, llama.cpp, LangChain, Vercel AI SDK, and additional compatible providers
  • Embedder functions built in — the same adapter pattern covers text embeddings, so you can reuse provider config for both chat and RAG
  • One-line local AI — ollama({ model: 'llama3.1' }) for fully offline agents with no API key required
  • CLI-backed agents — @agentskit/adapters/cli normalizes text, JSON, and ACP-based local LLM CLIs
  • LangChain bridge — @agentskit/adapters/langchain-bridge turns any adapter into a LangChain BaseChatModel for createAgent

Gateway and multimodal transport

openaiCompatible({ model, baseUrl, path, headers, fetch }) supports custom OpenAI-compatible endpoints; apiKey is optional and headers override defaults. openRouter aliases openrouter; cloudflareAiGateway and workersAi supply Cloudflare REST URLs without runtime bindings. Catalog URL variables are supplied explicitly through env, including CLOUDFLARE_ACCOUNT_ID.

OpenAI-compatible, Anthropic, Gemini/Vertex and Ollama serializers read message.parts. Unsupported sources/modalities raise CapabilityUnsupportedError with code: CAPABILITY_UNSUPPORTED when multimodal input is enabled. Models without multimodal capability fall back to text parts and short attachment markers, omitting binary data and data URLs, and log at most one warning per request. OpenAI and Anthropic assistant binary parts also use this text fallback. Explicit capabilities.multiModal takes precedence over model-name heuristics (GPT-4/5, o-series, vision, Gemini and Claude 3+ names, including provider prefixes). Set it explicitly for custom models or providers whose capabilities differ. See the tested modality matrix and configuration guide. These are local wire-format tests; live provider acceptance remains unverified.

Install

npm install @agentskit/adapters

The runtime example below also needs @agentskit/runtime. The RAG example also needs @agentskit/rag, @agentskit/memory, and the optional vectra peer (npm install @agentskit/rag @agentskit/memory vectra).

Quick example

import { anthropic } from '@agentskit/adapters'
import { createRuntime } from '@agentskit/runtime'

// Switch provider by swapping one import
const adapter = anthropic({ apiKey: process.env.ANTHROPIC_API_KEY, model: 'claude-sonnet-4-6' })
// const adapter = openai({ apiKey: process.env.OPENAI_API_KEY, model: 'gpt-4o' })
// const adapter = ollama({ model: 'llama3.1' })

const runtime = createRuntime({ adapter })
const result = await runtime.run('Summarize the latest AI news')
console.log(result.content)

Embeddings (for RAG)

Use the same package for vector embeddings — wire openaiEmbedder, geminiEmbedder, or ollamaEmbedder into @agentskit/rag:

import { openaiEmbedder } from '@agentskit/adapters'
import { createRAG } from '@agentskit/rag'
import { fileVectorMemory } from '@agentskit/memory'

const rag = createRAG({
  embed: openaiEmbedder({ apiKey: process.env.OPENAI_API_KEY! }),
  store: fileVectorMemory({ path: './vectors' }),
})

Features

  • Providers: Anthropic, OpenAI, Gemini, Ollama, DeepSeek, Grok, Kimi, Mistral, Cohere, Together, Groq, Fireworks, OpenRouter, Hugging Face, LM Studio, vLLM, llama.cpp, LangChain, LangGraph, Vercel AI SDK, generic ReadableStream
  • Embedders: openaiEmbedder, geminiEmbedder, ollamaEmbedder, deepseekEmbedder, grokEmbedder, kimiEmbedder, createOpenAICompatibleEmbedder
  • Fetch-backed adapters run against the shared Adapter contract v1 suite (ADR 0001); SDK-backed adapters have provider-specific contract and resilience coverage
  • Custom adapter authoring via createAdapter()
  • Higher-order adapters: createRouter (cost/latency/classifier), createEnsembleAdapter (fan-out + merge), createFallbackAdapter (ordered try-next)

CLI-backed adapters

The Node-only @agentskit/adapters/cli subpath runs an explicitly selected local LLM executable without a shell:

import { createCliAdapter, getCliProviderManifest, resolveCliManifest } from '@agentskit/adapters/cli'

const manifest = getCliProviderManifest('codex')
if (!manifest) throw new Error('provider manifest is unavailable')
const adapter = createCliAdapter(resolveCliManifest(manifest, { mode: 'review-safe' }))

The generic factories are createCliAdapter (exec-text), createJsonCliAdapter (exec-json), and createAcpCliAdapter (ACP v1 over JSON lines). The built-in manifests cover Codex, Claude Code (text and JSON output), Grok CLI, and OpenCode. resolveCliManifest keeps command, argv, protocol, provider id, and mode explicit; diagnoseCliProviderManifest verifies availability and an optional version pattern. review-safe is the default: no shell, automatic installation, native login, MCP, plugins, or terminal tools. Use trusted-local explicitly when a developer intentionally wants the CLI's local authentication and environment. requiredCapabilities is checked before spawning, and onDiagnostic receives redacted exit, timeout, abort, and output-limit data. Structured output fails closed; timeouts, aborts, output limits, and non-zero exits produce terminal adapter errors. Process termination is awaited before the adapter finishes, including when input or output fails. restricted-environment is an explicit environment allowlist mode; it is not an OS, filesystem, process, or network sandbox. Use @agentskit/sandbox when a real isolation boundary is required.

exec-text vs exec-json: what each protocol can return

The protocol decides which stream chunks a manifest can produce. Pick the manifest by what you need back, not by the CLI name:

ProtocolFactoryChunks emittedNot available
exec-textcreateCliAdaptertext (streamed), donestructuredOutput, reasoning, tool_call, usage
exec-jsoncreateJsonCliAdaptertext, reasoning, tool_call, usage, donestreaming (one response per process)
acpcreateAcpCliAdaptertext, reasoning (streamed), donetool calls (rejected), MCP, plugins, terminal

validateCliProviderManifest rejects a manifest that claims a capability its protocol cannot deliver, and requiredCapabilities fails before spawning for the same reason. In practice: the claude-code and codex manifests are exec-text and only ever yield plain text. For tool calls, usage, or structured output from Claude Code use claude-code-json instead.

The same table is enforced at compile time. CliProviderManifest is a union discriminated by protocol, capabilities is typed as CliCapabilitiesFor<protocol>, and getCliProviderManifest('claude-code') returns CliProviderManifestFor<'exec-text'>, so this does not type-check:

const manifest = getCliProviderManifest('claude-code')!
resolveCliManifest(manifest, { requiredCapabilities: { tools: true } })
//                                                    ^^^^^ not assignable: exec-text has no tools/structuredOutput

Claude Code

Two first-party manifests wrap the claude executable:

  • claude-code — claude -p, exec-text. Streams the final answer as text.
  • claude-code-json — claude -p --output-format json, exec-json. Parses the result envelope into text, tool_call, and usage chunks with session_id, total_cost_usd, duration_ms, and num_turns as metadata. is_error or a non-success subtype fails closed.
import { createJsonCliAdapter, getCliProviderManifest, resolveCliManifest } from '@agentskit/adapters/cli'

const manifest = getCliProviderManifest('claude-code-json')
if (!manifest) throw new Error('provider manifest is unavailable')
const adapter = createJsonCliAdapter(resolveCliManifest(manifest, { mode: 'trusted-local' }))

When the request carries context.tools, the tool list and a { text?, toolCalls } reply contract are appended to Claude Code's system prompt via --append-system-prompt; claude-code-json recognizes that object (fenced or bare) in the result string and emits tool_call chunks. Plain prose results stay text. structured_output from --json-schema is honored the same way. Tool execution itself remains the consumer's responsibility: the adapter never enables Claude Code's own tools, MCP, or plugins.

Prompt serialization

createCliAdapter and createJsonCliAdapter default to writing the raw AdapterRequest as one JSON line on stdin. That is the right contract for a purpose-built CLI, but agentic CLIs read stdin as a user prompt, and Claude Code refuses a raw JSON request containing systemPrompt as an apparent prompt-injection attempt. The first-party manifests therefore use two exported serializers:

  • serializeCliPrompt (used by codex) writes labelled blocks:

    [system]
    You are a reviewer.
    
    [user]
    review this
    
  • serializeCliMessages plus claudeCodeRequestArgs (used by claude-code and claude-code-json) writes only the conversation to stdin (a single user message is written bare) and passes the system prompt and the tool contract through --append-system-prompt. Verified live against Claude Code 2.1: the same instructions inside the user prompt, even as labelled [system] blocks, are flagged as an injection attempt, whereas through the system flag a request with context.tools comes back as a tool_call chunk.

A manifest may declare serializeRequest, requestArgs (extra per-request argv, appended after args), parseOutput, and parse; resolveCliManifest forwards them to the factory. buildCliSystemPrompt(request) returns the system prompt plus tool contract for other CLIs with a system-prompt flag.

Use buildArgs(request) only for CLIs that require the prompt in argv; it is request-aware and still uses direct, shell-free spawning. Set serializeRequest: () => '' when the provider does not consume stdin. For JSONL or event-wrapped output, parseOutput(stdout) can decode raw stdout before the normal parse(value) callback runs. For CLIs that write the final response to a file, outputFile reads that file after process completion with the same byte limit and abort handling.

LangChain bridge: use any adapter as a LangChain chat model

langchain() and langgraph() expose a LangChain runnable as an AdapterFactory. The @agentskit/adapters/langchain-bridge subpath goes the other way: adapterToLangChainModel(adapter) wraps any AdapterFactory (mock, Ollama, a CLI-backed adapter, ...) as a real BaseChatModel, so it can replace ChatAnthropic/ChatOpenAI in createAgent, AgentNode, or a plain chain. It needs @langchain/core (optional peer dependency).

import { createAgent } from 'langchain'
import { tool } from '@langchain/core/tools'
import { mockAdapter } from '@agentskit/adapters'
import { adapterToLangChainModel } from '@agentskit/adapters/langchain-bridge'

const add = tool(async ({ a, b }) => String(a + b), {
  name: 'add',
  description: 'Add two numbers',
  schema: { type: 'object', properties: { a: { type: 'number' }, b: { type: 'number' } }, required: ['a', 'b'] },
})
const model = adapterToLangChainModel(mockAdapter({ response: [/* ... */] }), { modelName: 'mock' })
const agent = createAgent({ model, tools: [add] })
  • bindTools() forwards LangChain tools (structured tools, OpenAI-format definitions, runnable tools) as AgentsKit ToolDefinitions on context.tools; tool_choice lands in context.metadata.toolChoice.
  • System messages become both a system message and context.systemPrompt; AI messages keep tool_calls; tool messages keep tool_call_id.
  • tool_call chunks become AIMessage.tool_calls (args parsed from JSON), usage chunks become usage_metadata, reasoning chunks land in additional_kwargs.reasoning, error chunks throw, and .stream() yields AIMessageChunks with tool_call_chunks.
  • Every response is a real AIMessage/AIMessageChunk instance, so wrapModelCall middleware and responseFormat work together. The default profile reports toolCalling and no native structuredOutput, so createAgent uses its tool strategy, which any tool-calling adapter can satisfy. Pass profile: { structuredOutput: true } only for adapters that honour a provider-side JSON schema.

Stream guarantees

  • A stream terminates exactly once with done or error; terminal errors carry an Error in metadata.error.
  • Fetch retries use @agentskit/net backoff and Retry-After parsing; the fetchWithRetry and adapter retry options keep their 3-attempt defaults. readSSELines remains as a deprecated compatibility wrapper; new parsers should consume parseSSE events directly.
  • SSE event data preserves whitespace and joins multiple data: fields with newlines. NDJSON readers flush a final UTF-8 chunk and accept a last record without a newline.
  • Provider streams that close before their native completion marker are treated as truncated, not successful.
  • abort(reason) propagates to active fetch readers and SDK requests and terminates with the same error semantics.
  • Native tool histories preserve call/result correlation. Parallel tool results are encoded in a single provider turn where required.
  • Credentials stay in provider headers when the protocol supports them; Gemini API keys are never placed in request URLs.
  • vercelAI consumes the Vercel AI SDK UI message stream v1 protocol, including its required response header and [DONE] marker.

Higher-order adapters

import { createRouter, anthropic, openai } from '@agentskit/adapters'

// Auto-pick cheapest capable candidate per request.
const router = createRouter({
  candidates: [
    { id: 'haiku', adapter: anthropic({ model: 'claude-haiku-4-5' }), cost: 0.25 },
    { id: 'sonnet', adapter: anthropic({ model: 'claude-sonnet-4-6' }), cost: 3 },
    { id: 'gpt-mini', adapter: openai({ model: 'gpt-4o-mini' }), cost: 0.15 },
  ],
})

See Adapter router, Ensemble, and Fallback chain.

Ecosystem

PackageRole
@agentskit/coreAdapter, EmbedFn, types
@agentskit/runtimeHeadless createRuntime
@agentskit/ragcreateRAG + embedders
@agentskit/memoryVector + chat memory backends

Testing Adapters

Three built-in utilities let you test agents without hitting a real LLM.

mockAdapter — deterministic responses

import { mockAdapter } from '@agentskit/adapters'

const adapter = mockAdapter({
  response: [
    { type: 'text', content: 'Hello!' },
    { type: 'done' },
  ],
})

Pass a function to make responses request-aware, or pass an array of arrays to return different chunks on each call (sequenced mode). Use the optional history array to capture every request for assertions.

recordingAdapter + inMemorySink — capture real calls

import { recordingAdapter, inMemorySink, anthropic } from '@agentskit/adapters'

const sink = inMemorySink()
const adapter = recordingAdapter(
  anthropic({ apiKey: process.env.ANTHROPIC_API_KEY!, model: 'claude-sonnet-4-6' }),
  sink,
)
// Runs the real LLM and captures every chunk to sink.fixture

replayAdapter — replay captured fixtures

import { replayAdapter } from '@agentskit/adapters'
import fixture from './fixture.json'

const adapter = replayAdapter(fixture) // no network calls

Typical workflow: record once in dev → commit JSON fixture → replay in CI.

Contributors

AgentsKit contributors

License

MIT — see LICENSE.

Docs

Full documentation · GitHub

Maturity and compatibility

  • Stability: beta — see docs/STABILITY.md
  • The implementation is hardened for a future freeze, but promotion still requires the 90-day beta window, two released minor lines, accepted package RFC, and repository evidence required by ADR 0024.
  • Node.js 20+ and TypeScript strict mode
  • Published as @agentskit/adapters

Contributing

See CONTRIBUTING.md and the monorepo LICENSE.

版本与发布记录

@agentskit/adapters 共发布 44 个版本,首次发布于 2026/04/06;过去 12 个月发布了 44 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.19.2latest2026/10/2611 天前
0.19.12026/10/2412 天前
0.19.02026/10/1026 天前
0.18.12026/10/031 个月前
0.18.02026/10/031 个月前
0.17.42026/09/291 个月前

关于 @agentskit/adapters 的常见问题

@agentskit/adapters 是什么?

Provider adapters for AgentsKit.

如何安装 @agentskit/adapters?

在项目目录运行 npm install @agentskit/adapters,或使用 pnpm add / yarn add / bun add。

@agentskit/adapters 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@agentskit/adapters 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@agentskit/adapters 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20.19。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@agentskit/adapters 可以商用吗?

@agentskit/adapters 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@agentskit/adapters 的下载量有多少?

根据 npm 官方下载统计,@agentskit/adapters 在 2026/10/05 – 2026/11/03 这 30 天内被下载 13,991 次,日均约 466 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@agentskit/adapters 还在维护吗?

最新版本 0.19.2 发布于 2026/10/26(11 天前);至今共发布 44 个版本,其中过去 12 个月发布了 44 个;首次发布于 2026/04/06。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。