Skip to content

JavaScript / TypeScript SDK

@opencorvus-ai/sdk reference for the generated OpenCorvus REST client.

Package: @opencorvus-ai/sdk Source: packages/sdk/js/ Generated from: packages/sdk/openapi.json

The SDK is a typed wrapper around the OpenCorvus REST API. HTTP methods, request types, response types, and SSE helpers are generated by @hey-api/openapi-ts; src/client.ts and src/server.ts add OpenCorvus-specific client/server helpers.

Install

Terminal window
bun add @opencorvus-ai/sdk

Client

import { createOpenCorvusClient } from "@opencorvus-ai/sdk"
const client = createOpenCorvusClient({
baseUrl: "http://127.0.0.1:7878",
password: process.env.OPENCORVUS_SERVER_PASSWORD,
})

createOpenCorvusClient() accepts the generated fetch-client config plus OpenCorvus additions:

OptionPurpose
baseUrlOpenCorvus server URL. Defaults to the generated server default.
directoryAdds the directory query parameter to project-scoped requests. Windows MSYS paths like /c/repo are normalized.
usernameBasic Auth username. Defaults to opencorvus.
passwordBasic Auth password. Use OPENCORVUS_SERVER_PASSWORD when the server is protected.
headersExtra headers. An explicit Authorization header is preserved and not replaced by password.
fetchCustom Fetch implementation for proxying, tracing, tests, or in-process adapters.
throwOnErrorWhen true, failed responses throw instead of returning { error }.
responseStyleGenerated client response mode: default fields object, or "data" for data-only responses.

Calls and Return Values

By default, non-SSE methods return a fields object:

const result = await client.task.create({
request: "Add unit tests for src/foo.ts",
})
if (result.error) throw result.error
const taskID = result.data.task_id

For data-only responses, set responseStyle: "data" globally or per call:

const client = createOpenCorvusClient({
baseUrl: "http://127.0.0.1:7878",
responseStyle: "data",
})
const task = await client.task.create({
request: "Add unit tests for src/foo.ts",
})

SSE

SSE methods return { stream }, where stream is an AsyncGenerator.

const abort = new AbortController()
const { stream } = client.event.subscribe(undefined, {
signal: abort.signal,
sseMaxRetryAttempts: 10,
})
for await (const event of stream) {
console.log(event.type, event)
}

Useful SSE options: signal, onSseEvent, onSseError, sseDefaultRetryDelay, sseMaxRetryDelay, and sseMaxRetryAttempts.

Embedded Server

Use createOpenCorvus() when the caller should launch an OpenCorvus server process and receive a connected client.

import { createOpenCorvus } from "@opencorvus-ai/sdk"
const { client, server } = await createOpenCorvus({
port: 0,
config: { logLevel: "info" },
})
try {
const health = await client.global.health({ throwOnError: true })
console.log(health.data)
} finally {
await server.close()
}

Return shape:

{
client: OpenCorvusClient
server: {
url: string
close: () => Promise<void>
}
}

If OPENCORVUS_SERVER_PASSWORD is set, createOpenCorvus() passes it into the returned client automatically.

Namespaces

The SDK follows OpenAPI operationId names. Dotted segments become namespaces and snake_case method names become camelCase. For example, session.prompt becomes client.session.prompt().

NamespaceExamples
client.global.*health, event, config.get, db.reset
client.task.*create, list, message, retry, replan, followup
client.session.*create, prompt, events, trace, summarize
client.goal.*Delivery Slice creation, immutable revision, and derived-progress routes
client.channel.*Channel runtime and attachment routes
client.mcp.*MCP server lifecycle and auth routes
client.permission.*Permission reply/reject routes
client.provider.*Provider model, auth, and refresh routes

Use HTTP API reference as the exhaustive operation list; each operationId maps directly to the SDK namespace/method shape above.

Expert Squad authoring

The Node-only @opencorvus-ai/sdk/expert-squad-authoring export writes a new canonical package directory and validates static cooperation across independently installed squads.

Use virtual_workflows: {} for simple direct dispatch. Every nonempty workflow identifies one complete Task-level collaboration variant and mandatory dependencies; every node runs once per Task. Delivery Slice subjects are typed dispatch/evidence references, not node scope. The SDK and Registry validate shape, exact projected-agent/dependency references, canonical ordering, and acyclic graphs without forcing one role topology.

Every projected Agent inherits the platform fact/Turn protocol selected by base_role. Package prompts may add domain rules, but they do not define a terminal-report/finalizer protocol or copy Host observations into an Agent-owned result. Domain tools record durable facts; normal stream end is a physical Turn observation; terminal delivery references the real final message or error/tool event. Dispatch lineage and execution attempts are immutable physical evidence. Task owns lifecycle; its completion decision cites current accepted Slice revisions, workflow/package identity, and typed EvidenceLocators.

Every scheduler and worker automatically receives the Core-owned artifact_search, artifact_read, and artifact_select discovery/provenance transport, even when its projection sets inherit_base_tools: false. Schedulers additionally receive read-only artifact_snapshot to freeze exact Task input files before dispatch; projected workers receive artifact_snapshot and artifact_publish for evidence resources and outputs. Schedulers never receive generic artifact_publish. A worker publishes current-Task project files with artifact_snapshot, then passes the returned exact content-addressed resource_set locator to artifact_publish; resource_set is required and is null when there are no files. The Host verifies the immutable manifest and expands its refs in canonical UTF-8 byte path order inside the trusted boundary, so the model transport remains compact regardless of file count. Downstream Agents pass short Host-minted artifact_locator_ref values to artifact_read, continue every byte window, and pass artifact_read_ref to artifact_select instead of reconstructing immutable locator JSON. The exported discovery, publish, and combined constants document these reserved capabilities; packages do not add their IDs to built_in_tool_ids and cannot shadow them. A worker without a typed domain-output producer calls artifact_publish with canonical JSON, an expert_output type under <active-squad-id>/..., and publication-specific source_selection_refs returned by earlier selections in the same physical Turn; the Host restores and persists complete canonical source locators. Existing typed domain-output tools and package tools remain their domain’s sole publishers and must not duplicate the same fact through artifact_publish. Search explicitly selects version_scope=current|historical|all, exact labels and provenance facets, query.mode=substring|fuzzy, and sort=relevance|newest|oldest|name; queryless current-scope enumeration remains valid. Fuzzy results are candidates, never automatic evidence selection. Complete but unselected reads remain observations; zero selections are valid. Search results are byte-bounded cursor pages and may contain fewer entries than the requested limit; follow next_cursor until null. Package-tool code remains a separate typed ABI: it consumes canonical locators with readExactArtifact(host, locator) and publishes explicit source_artifact_locators. Ordinary dispatch outcomes and Agent messages do not transport domain Artifact inventories, locators, or bodies. Cross-Task imported envelopes preserve the source Artifact’s original consumption provenance inside immutable import_lineage; target-Task observed/selected provenance remains target-local. A user-pinned locator must be read exactly and cannot be replaced with a search result. Zero search results and absent optional domain fields are valid observations. Missing selected references, foreign-Task ownership, wrong paths or digests, corrupt manifests or bytes, and unreadable text are explicit evidence errors.

Engine Artifact publication has two explicit surfaces. A model-facing projected worker invokes artifact_publish and supplies strict JSON text in payload_json. TypeScript inside a package tool instead calls context.host.engineArtifacts.publish({ artifact_type, schema_version, label, payload, resources, source_artifact_locators }); it never calls or wraps the model-facing tool. Separately, package tools publish immutable Task Artifact files through context.host.taskArtifacts.stage(...) followed by context.host.taskArtifacts.publish(...) and return the typed snapshot locator. An ordinary package-tool return string is only the visible tool result and never publishes an Artifact.

Every package Engine Artifact publisher declares one stable namespaced type, positive schema version, stable label, canonical JSON payload, explicit resources ([] when none), and explicit source locators ([] when none). It returns only a compact locator and sha256 receipt. Package Engine and Task publication is always idempotent at the ToolHost boundary; package code has no idempotent field and cannot opt out of stable exact retries. Consumers still discover the durable authority with artifact_search, completely read its exact locator with artifact_read, and call artifact_select; the receipt is not evidence transport. Package tools publish large, binary, or multi-file resources through taskArtifacts and return the typed immutable snapshot locator rather than inventing an Engine Artifact envelope. The public envelope and locator schemas come from @opencorvus-ai/plugin/artifact-catalog, not a second SDK schema. A scheduler-projected Engine Artifact publisher should be invoked only after a complete exact current-type/label search returns zero matches, then followed by search, complete read, and selection. On resume, one existing current authority is reused without republishing; ambiguous or incomplete catalogs are explicit blockers. ExpertSquadCollaborationDefinition consumes and produces values describe semantic evidence topology only. They do not configure transport, inventory values, copy payloads, or create a renderer.

Package-defined values passed to context.metadata(...) are exposed under the result’s package_metadata namespace. Top-level provenance, truncation, and lifecycle-control metadata is Host-owned and cannot be replaced by package code.

A Requirements worker registers domain facts and ends with a visible narrative summary. The adapter persists the immutable RequirementSet; downstream Task-level nodes discover it by immutable producer/type/workflow/node provenance and read its exact locator. Slice revisions can cite that locator without becoming execution owners.

Cross-Task authority remains closed. A dependent Mission stage references a completed predecessor only with panel.create_task.artifact_sources shaped as {authority: "completion_decision", source_task_id}. The Host reads that source Task’s current Completion Decision and atomically imports its complete deliverable_artifact_locators set, so the model never copies immutable locator IDs. Failed or cancelled recovery uses the same discriminated input with {authority: "terminal_lifecycle", source_task_id, locator} and is fenced by the current typed terminal lifecycle. The target catalog exposes target-owned imported Engine Artifacts preserving source type, schema, payload, copied resources, and immutable import_lineage. Task request prose, naked source identifiers, late imports, latest-wins selection, and foreign-Task reads are not evidence transport.

import {
analyzeExpertSquadWorkflowTopology,
EXPERT_SQUAD_PLATFORM_ARTIFACT_DISCOVERY_TOOL_IDS,
EXPERT_SQUAD_PLATFORM_ARTIFACT_PUBLISH_TOOL_IDS,
EXPERT_SQUAD_PLATFORM_ARTIFACT_TOOL_IDS,
validateExpertSquadCollaboration,
validateExpertSquadManifestDispatchTopology,
validateExpertSquadPackageDefinition,
validateExpertSquadSourceCapabilities,
writeExpertSquadPackage,
type ExpertSquadCollaborationDefinition,
type ExpertSquadSourceCapabilityContract,
} from "@opencorvus-ai/sdk/expert-squad-authoring"
console.assert(
EXPERT_SQUAD_PLATFORM_ARTIFACT_DISCOVERY_TOOL_IDS.join(",") === "artifact_search,artifact_read,artifact_select",
)
console.assert(EXPERT_SQUAD_PLATFORM_ARTIFACT_PUBLISH_TOOL_IDS.join(",") === "artifact_snapshot,artifact_publish")
console.assert(EXPERT_SQUAD_PLATFORM_ARTIFACT_TOOL_IDS.length === 5)
validateExpertSquadManifestDispatchTopology(packageDefinition.manifest)
const workflowTopology = analyzeExpertSquadWorkflowTopology(packageDefinition.manifest)
validateExpertSquadPackageDefinition(packageDefinition)
await writeExpertSquadPackage({ directory: sourceDirectory, definition: packageDefinition })
const cooperation: ExpertSquadCollaborationDefinition = {
schema_version: 1,
stage_execution: "mission_task",
id: "research-to-build",
label: "Research to build",
inputs: ["task-brief"],
outputs: ["build-evidence"],
stages: [researchStage, buildStage],
}
validateExpertSquadCollaboration({ definition: cooperation, manifests: [researchManifest, buildManifest] })
const sourceContract: ExpertSquadSourceCapabilityContract = JSON.parse(sourceContractText)
validateExpertSquadSourceCapabilities({
definition: sourceContract,
collaborations: [cooperation],
manifests: [researchManifest, buildManifest],
})

The package validator is the authoring hook for every newly authored Expert Squad. The SDK owns the portable manifest v1 runtime schema, generic graph integrity, package path ownership, and required README, selector, and projected prompt entrypoints. analyzeExpertSquadWorkflowTopology() returns deterministic initial frontiers, dependency-depth waves, join nodes, critical-path node counts, and maximum widths so authors can inspect accidental serialization. It is read-only: it adds no manifest field, minimum-width rule, Runtime state, or scheduling gate. Registry reuses that exact v1 schema and adds runtime-template, resource-closure, filesystem, and installation-environment validation. The renderer validates before producing files; the writer publishes a fully written same-parent staging directory with one rename. The collaboration validator requires stage_execution: "mission_task", canonical unique stage/evidence IDs, exact manifest and workflow references, earlier-stage dependencies, connected evidence, and unique producers. These are pure authoring checks and do not install packages, create Tasks or Goals, dispatch agents, persist workflow state, or auto-advance stages. Use client.expertSquad.validateFolder() for Registry-owned closure validation and an explicit import call for installation.

Generation

Regenerate OpenAPI, SDK types, and generated client code:

Terminal window
bun ./packages/sdk/js/script/build.ts

Regenerate/check the web API reference from the generated OpenAPI spec:

Terminal window
bun run docs:api
bun run docs:check

Generated SDK source lives under packages/sdk/js/src/gen/. Do not edit generated files by hand.

Exports and Compatibility

Use the package root:

import { createOpenCorvusClient, createOpenCorvus } from "@opencorvus-ai/sdk"

There is no current @opencorvus-ai/sdk/v2 subpath. The root package exposes the createOpenCorvus* APIs; legacy-prefixed export names are not part of the current contract.