Skip to content

About

🛰️ Talk to any AI agent runtime through one TypeScript client. Provider-agnostic, ESM, zero-dependency.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

1 watching

Forks

Latest commit

 

History

443 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@cavi-ai/api-client

One application. Several agent runtimes.

License: MIT CI

Give users a choice of runtime without writing another progress renderer, batch collector, or failure handler for each backend. @cavi-ai/api-client adapts Claude, Codex, AGY, OpenCode, Hermes, and OpenClaw to shared TypeScript contracts.

Your application consumes run IDs, statuses, text, token usage, and stream events. Provider adapters own the HTTP, SSE, or WebSocket mapping. Capabilities tell your application which features to offer; unsuccessful calls carry a structured gap.

Where it helps

You are building The package gives you
An assistant UI with a runtime selector One stream event handler for text, tools, approvals, and terminal states
A service that starts background work A shared run/status contract for retrieval and cancellation
A batch processing job Request correlation by customId and per-item success/failure results
A gateway dashboard Sessions, models, usage, tasks, and workspace access, gated by the configured backend

The package is ESM, includes TypeScript declarations, has no runtime dependencies, and keeps React optional. Models, credentials, native tools, and persistence still belong to the provider. Installing the package does not install a runtime.

Version 0.21.0 includes explicit OpenCode v2 polling clients, profile-aware Hermes dashboard control, and opt-in observed completion for Managed Agents and canonical OpenClaw outcomes. See the provider compatibility guide for setup and supported boundaries.

If your application only needs one provider's native API and no shared workflow, its direct SDK may be simpler. This package is useful when the integration boundary needs to survive another backend.

Build an answer service

Use Node.js 20 or later and keep provider credentials on your server.

npm install @cavi-ai/api-client

Put this factory in your server application. Supply your Anthropic API key and an account-accessible model from server configuration. It creates a reusable service that returns text, run identity, and usage to its caller.

import { ApiClientError, createApiClient, createRuntimeProviderRegistry } from "@cavi-ai/api-client";
import { createClaudeProviderModule } from "@cavi-ai/api-client/providers/claude/messages";

export function createAssistant(config: { apiKey: string; model: string }) {
  const registry = createRuntimeProviderRegistry({
    modules: [createClaudeProviderModule({ apiKey: config.apiKey })],
  });
  const client = createApiClient("claude", { registry, defaultTimeoutMs: 30_000 });

  return {
    async answer(question: string) {
      const result = await client.startRun({ model: config.model, input: question });
      if (!result.ok) return result;

      const run = result.data;
      if (run.status !== "completed") {
        const code = run.status === "failed" ? "run_failed"
          : run.status === "cancelled" ? "run_cancelled" : "run_incomplete";
        throw new ApiClientError(`Run ${run.run_id} has no completed answer (status: ${run.status})`, {
          type: "run", code, cause: run,
        });
      }
      const text = run.output ?? run.response;
      if (text === undefined) {
        throw new ApiClientError(`Run ${run.run_id} completed with no text`, {
          type: "run", code: "run_output_missing", cause: run,
        });
      }
      return {
        ok: true as const,
        source: result.source,
        data: { runId: run.run_id, text, tokens: run.tokens },
      };
    },
    dispose: () => client.dispose(),
  };
}

Call assistant.answer(question) on the service returned by createAssistant. When result.ok is true, use result.data.text in your HTTP response, saved record, or UI. When it is false, handle result.gap.reason; retain the gap for diagnostics. Authentication errors, unclassified failures, unsuccessful runs, and missing text reject, so use your server's exception boundary.

The service's exceptions use ApiClientError: run_failed, run_cancelled, run_incomplete, or run_output_missing. Narrow with isApiClientError and branch on code; keep cause in protected diagnostics for run reconciliation. Version 0.19.0 adds ApiClientErrorCode.Run* and ApiClientErrorType.Run; the example uses string values to also support older releases. See error handling for guards and safe application responses.

Version 0.19.0 adds requireRunText(run) and requireStreamText(stream) to replace those execution checks with package APIs. Completion-only helpers also support tool-oriented runs without requiring text. See the development guide and complete examples. The quickstart above also supports releases without these helpers.

For background workflows, 0.19.0 also provides waitForRun with time and poll budgets, caller cancellation, and the last observed run retained. Stopping a local wait leaves backend work running. The development guide includes a complete background answer example. The authorized background workflow shows stored-owner checks for retrieval, polling, and explicit cancellation.

Version 0.19.0 exposes structured execution failure details for Codex responses/streams and Claude Messages error streams. Branch on observed provider codes or reasons without parsing diagnostic messages; completion helpers retain those details in their error causes.

The factory above is example application code, not an exported package API. It uses Claude Messages' synchronous lifecycle. Background adapters need retrieval; they do not promise an answer when startRun returns. Create one service per credential/configuration scope, reuse it, and call assistant.dispose() when its owner shuts down.

Integrate the workflow you need

  • Test your server integration: runnable application tests for answers, progress, validation, and safe failures.

  • First response: reusable service and result handling.

  • Server requests: validate input and return run state through an application endpoint.

  • Provider setup: credentials, model selection, and backend requirements.

  • Streaming: send deltas to your UI and distinguish call failure from run failure.

  • Background runs and batches: bound local waits and preserve IDs for later retrieval.

  • HTTP integration: response ownership, typed errors, and tested development examples.

  • Errors: gaps, exceptions, and safe retry decisions.

Prefer createApiClient for applications. Its CapabilityClient keeps accessors present and returns CapabilityResult<T>. Use the raw RuntimeClient when implementing an adapter or managing the execution contract directly; its optional methods return raw values and can throw.

Project references

Version 0.21.0 includes Python runtime access for all seven runtime providers. Native installation requires no Node/npm; the optional bridge supports application-owned TypeScript adapters.

Migration · Changelog · Architecture · Contributing · Security

Versioned documentation ships in the package under docs/api-client/v<documented version> for offline reading. The site ingests the GitHub release docs artifact; merging documentation changes alone does not refresh an already published release. See the host ingestion contract.

License

MIT

About

🛰️ Talk to any AI agent runtime through one TypeScript client. Provider-agnostic, ESM, zero-dependency.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages