@agenticprimitives/orchestration-openai-compat
Part of Agentic Primitives — the open-source trust substrate for agentic applications: identity that can sign, authority checked at act time, evidence the owner carries. Developer kit · All packages
The OpenAI-compatible LLM binding for the @agenticprimitives/orchestration Planner
and AnswerComposer ports — the in-repo adapter (the chain-state / chain-state-viem pattern), sibling to
orchestration-anthropic. The pure orchestration core stays vendor-free; the
chat-completions translation lives here.
Vendor-neutral. This package names no host and no model. Groq, Ollama, OpenRouter, a self-hosted vLLM: each
is a baseUrl + model you supply.
Install
pnpm add @agenticprimitives/orchestration-openai-compat @agenticprimitives/orchestration
Quick start (Groq)
import { runIntent, type ToolSpec } from '@agenticprimitives/orchestration';
import { createOpenAiCompatPlanner, createFetchOpenAiCompatClient } from '@agenticprimitives/orchestration-openai-compat';
const tools: ToolSpec[] = [
{ id: 'get_vault_record', description: 'Read a vault record by recordType.', inputSchema: { type: 'object', properties: { recordType: { type: 'string' } }, required: ['recordType'] } },
{ id: 'get_pii', description: 'Read the principal’s PII (high sensitivity).' },
];
// Dependency-free client — works in a Cloudflare Worker (no SDK, no node shims). The host is YOUR choice.
const client = createFetchOpenAiCompatClient({ apiKey: env.GROQ_API_KEY, baseUrl: 'https://api.groq.com/openai/v1' });
const planner = createOpenAiCompatPlanner({ client, model: 'openai/gpt-oss-120b', label: 'groq' });
const result = await runIntent(
{ goal: 'show me my profile' },
{ planner, tools, invoke: async (toolId, args) => myDelegatedMcpCall(toolId, args) },
);
The model chooses which tool fits the goal; the chosen call still rides the task's on-chain delegation at the invoker (ADR-0041). The model never gains authority by being asked.
What else is here
createOpenAiCompatComposer({ client, model })— turns what the tools returned into a grounded sentence.createOpenAiCompatStructuredCall({ client, model })— one forced single-tool call (a query, a selection).OpenAiCompatHttpError— thrown on a non-OK response withstatusand, on a 429,retryAfterSeconds. Say it to the person; never route to another vendor because of it.
OpenAiCompatLike
Every factory takes a structural OpenAiCompatLike client (the minimal chat.completions.create surface).
Pass either createFetchOpenAiCompatClient({ apiKey, baseUrl }) or the official new OpenAI({ apiKey, baseURL })
— it satisfies the same shape. This keeps the adapter unit-testable with a fake and avoids a hard SDK dependency.
Wire notes
- Tool
argumentsarrive as a JSON string; the adapter parses them. Unparseable →planner_failed. tool_choice: 'required'is a request; a prose-only reply isno_plan.- The client is non-streaming. Fine for planning / answering budgets; a very long generation may hit an intermediary timeout until streaming lands.
Boundaries
Imports only @agenticprimitives/orchestration (+ types). See spec.md + capability.manifest.json.
License
MIT