Skip to content

SDK Guide ​

@giggle-ai/runtime-sdk is a thin, fully typed TypeScript client. Every method is one request/response round trip against the engine's REST API — no policy, risk, or state-machine logic is duplicated client-side.

Three clients, not one ​

As of Milestone 2D the SDK is split into three classes, one per credential plane the engine actually enforces server-side (see Security). A credential minted for one plane is rejected by the routes another plane's client calls — this isn't just an API convenience, it mirrors a real authorization boundary:

ClientCredentialTalks to
CarcManagementClienta tenant principal's management-api-key/service-account-key/runtime/* tenant-facing routes (Agent Registry, Sessions, Agent Runs, Provider Connections, Execution Profiles, Policies, Decision Records/Replay, Metrics, and the tenant-facing slice of Integration Governance)
CarcAdminClienta platform_admin principal's credentialevery /admin/* route — ManagementPrincipal/TenantMembership/PrincipalCredential lifecycle, Organization Verification, and the full admin side of Integration Governance (integrations, environments, agent bindings, certifications, credential bindings, audit)
CarcRuntimeClientan opaque IntegrationCredentialBinding reference (never a management credential)only POST /runtime/agents/:id/execute — the machine-to-machine execution gateway

If your integration only ever calls tenant-facing routes, you only ever need CarcManagementClient. If it also administers platform-wide state (rare — usually only the platform team itself) or executes agents as the machine-to-machine integration runtime (the actual production traffic path once your integration is certified and active), construct the other two clients as well — see examples/openai-clinical-agent/ in this monorepo for a worked example that genuinely needs all three side by side.

Installing ​

bash
npm install @giggle-ai/runtime-sdk

Inside this monorepo, it's already a workspace package — build it (and its dependencies) with npm run build:packages.

CarcManagementClient ​

ts
import { CarcManagementClient } from "@giggle-ai/runtime-sdk";

const runtime = new CarcManagementClient({
  baseUrl: process.env.CARC_RUNTIME_API_URL!,
  managementCredential: process.env.CARC_MANAGEMENT_CREDENTIAL!, // see Security — required once MANAGEMENT_AUTH_MODE=enforced
  tenantId: "tenant_acme_health", // optional selection hint among your principal's own active memberships
  timeoutMs: 30_000, // default; set 0 to disable
});
FieldRequiredNotes
baseUrlyesNo trailing slash required.
managementCredentialin enforced modeSent as Authorization: Bearer <managementCredential>. Issued via CarcAdminClient.issuePrincipalCredential — see Security and Integration Governance & Identity.
tenantIdnoSent as X-Tenant-ID — only ever a selection hint among your principal's own active memberships in enforced mode, never a way to grant yourself a different tenant.
headersnoExtra headers merged into every request.
timeoutMsnoAborts a request after this many ms.
fetchnoOverride the fetch implementation (mocking, polyfills).

Timeout configuration ​

Every request is wrapped in an AbortController timing out after timeoutMs (default 30000). A timeout surfaces as RuntimeNetworkError.

Correlation IDs ​

Every request automatically sends a generated X-Correlation-ID (or reuses whatever the engine echoes back). Read the most recent one via runtime.getLastCorrelationId(), or .correlationId on any thrown SDK error — include it when filing an issue about a specific request. All three clients share this behavior identically.

Error handling ​

Every failure across all three clients is a subclass of the same RuntimeApiError hierarchy:

ts
import { RuntimeConflictError, RuntimeNotFoundError } from "@giggle-ai/runtime-sdk";

try {
  await runtime.activateAgent("some-agent");
} catch (err) {
  if (err instanceof RuntimeConflictError) {
    console.log(`Cannot activate: ${err.message} (correlation: ${err.correlationId})`);
  } else if (err instanceof RuntimeNotFoundError) {
    console.log("Agent not registered.");
  } else {
    throw err;
  }
}

See Errors for the full hierarchy and retryable/non-retryable guidance.

Agent Registry methods ​

ts
await runtime.listDomains(); // installed domain packs, with their roles and task types
await runtime.listCases(); // synthetic cases across every domain
await runtime.registerAgent({ agentId, name, owner, version, domain, subdomain, allowedTasks, capabilities, modelProvider, modelVersion, riskTier });
await runtime.listAgents({ status: "active" });
await runtime.getAgent(agentId);
await runtime.updateAgent(agentId, { version: "1.1.0" });
await runtime.activateAgent(agentId);
await runtime.suspendAgent(agentId);
await runtime.deprecateAgent(agentId);

Session methods ​

ts
await runtime.createSession({ caseId, agentId, taskType, userRole });
await runtime.listSessions({ state: "waiting_for_human_review" });
await runtime.getSession(sessionId);
await runtime.getSessionTimeline(sessionId);
await runtime.pauseSession(sessionId, { reason });
await runtime.resumeSession(sessionId);
await runtime.cancelSession(sessionId, { reason });
await runtime.approveSession(sessionId, { reviewerId, notes });
await runtime.rejectSession(sessionId, { reviewerId, notes });
await runtime.retrySession(sessionId, { reviewerId, notes });

Agent Run methods ​

ts
await runtime.submitAgentRun({ agentId, caseId, taskType, agentOutput, sourceReferences, modelProvider, modelVersion, submittedBy });
await runtime.listAgentRuns({ agentId, executionOrigin: "external" });
await runtime.getAgentRun(runId);

Provider Connection methods ​

Initiative 2 — tenant-owned connections to external model providers. See Provider Connections for the full architecture. credential is write-only and never returned by any of these methods. Contains no model/execution configuration — see Execution Profile methods below for that.

ts
const connection = await runtime.createProviderConnection({
  provider: "openai",
  displayName: "Acme Health — OpenAI Production",
  credential: process.env.ACME_OPENAI_API_KEY!,
});
await runtime.validateProviderConnection(connection.connection_id);

await runtime.listProviderConnections({ status: "valid" });
await runtime.getProviderConnection(connection.connection_id);
await runtime.updateProviderConnection(connection.connection_id, { displayName: "Renamed" });
await runtime.rotateProviderConnectionCredential(connection.connection_id, newApiKey);
await runtime.disableProviderConnection(connection.connection_id);
await runtime.enableProviderConnection(connection.connection_id);
await runtime.deleteProviderConnection(connection.connection_id);

Execution Profile methods ​

Initiative 3 — the canonical execution contract (model, inference parameters, timeouts/retries). See Execution Profiles for the full architecture and resolution order.

ts
const profile = await runtime.createExecutionProfile({
  displayName: "GPT-5 Structured Review",
  provider: "openai",
  adapterId: "openai-responses-adapter",
  providerConnectionId: connection.connection_id,
  model: "gpt-5",
  temperature: 0.2,
  maxOutputTokens: 2048,
});
await runtime.activateExecutionProfile(profile.profile_id);

await runtime.listExecutionProfiles({ status: "active" });
await runtime.getExecutionProfile(profile.profile_id);
await runtime.updateExecutionProfile(profile.profile_id, { temperature: 0.1 });
await runtime.disableExecutionProfile(profile.profile_id);
await runtime.deleteExecutionProfile(profile.profile_id);

Set the resulting profile_id on an agent before calling CarcRuntimeClient.executeRegisteredAgent (below):

ts
await runtime.updateAgent(agentId, {
  executionProfileId: profile.profile_id,
});

Integration Governance methods (tenant-facing) ​

The limited, tenant-facing slice of Integration Governance — see Integration Governance & Identity for the full lifecycle and everything intentionally NOT reachable here (sandbox/ production approval, certification pass/fail, activation — all platform-admin-only, on CarcAdminClient instead):

ts
const integration = await runtime.createIntegration({ name, integration_type, owner_team, technical_contact });
await runtime.updateIntegration(integration.id, { description: "Updated description" });
await runtime.submitIntegration(integration.id);

await runtime.listIntegrations();
await runtime.getIntegration(integration.id);
await runtime.listIntegrationEnvironments(integration.id);
await runtime.listEnvironmentCertifications(environmentId);
await runtime.listEnvironmentAgentBindings(environmentId);
await runtime.rotateIntegrationCredential(credentialBindingId, { raw_credential, reason });

Decision record methods ​

ts
await runtime.getDecisionRecord(decisionId);
await runtime.listDecisionRecords(status);

Replay methods ​

ts
await runtime.getDecisionReplay(decisionId); // single-run replay
await runtime.getSessionReplay(sessionId); // full multi-run "flight recorder"

Metrics methods ​

ts
await runtime.getMetrics({ agent_id, task_type, from, to });

Policy methods ​

ts
await runtime.listPolicies({ enabledOnly: true });
await runtime.getPolicy(policyId);

Health and identity methods ​

ts
await runtime.getHealth();
await runtime.getReadiness();
await runtime.getVersion();
await runtime.whoami(); // the authenticated principal's own identity — principal_id, principal_type, tenant_id, roles, environment

CarcAdminClient ​

Platform-admin-only — construct with an adminCredential (a platform_admin principal's credential), never a tenant management credential:

ts
import { CarcAdminClient } from "@giggle-ai/runtime-sdk";

const admin = new CarcAdminClient({
  baseUrl: process.env.CARC_RUNTIME_API_URL!,
  adminCredential: process.env.CARC_ADMIN_CREDENTIAL!,
});

Unlike CarcManagementClient, there is no client-level tenantId — every governance-admin method takes an explicit tenantId as its first parameter and sends it as a per-call X-Tenant-ID override, since a platform admin routinely acts across many different tenants in the same session.

ts
// Adapter methods (moved here from CarcManagementClient in Milestone 2D)
await admin.listAdapters();
await admin.getAdapter(adapterId);
await admin.validateAdapter(adapterId);

// Identity
await admin.whoami();
await admin.getBootstrapStatus();
await admin.createManagementPrincipal({ principal_type: "tenant_user", display_name: "Acme Ops" });
await admin.activateManagementPrincipal(principalId);
await admin.createTenantMembership(principalId, { tenant_id: "tenant_acme", role: "tenant_owner" });
await admin.issuePrincipalCredential(principalId, { credential_type: "management-api-key", environment: "production" });

// Integration Governance (admin) — see /integration-governance for the
// full lifecycle
await admin.submitOrganizationVerification({ tenant_id, legal_name, registration_number, country_code });
await admin.approveOrganizationVerification(verificationId, { reviewed_by });
await admin.approveSandbox(tenantId, integrationId);
await admin.requestIntegrationCertificationStage(tenantId, integrationId);
await admin.approveProduction(tenantId, integrationId, { approved_by });
await admin.activateIntegration(tenantId, integrationId);
await admin.createIntegrationEnvironment(tenantId, integrationId, { environment: "production" });
await admin.bindIntegrationCredential(tenantId, environmentId, { credential_type: "api-key", raw_credential });
await admin.rotateIntegrationCredentialBinding(tenantId, credentialBindingId, { raw_credential, reason });

// The unified audit timeline's two source streams (see /integration-governance)
await admin.listIntegrationGovernanceAuditEvents(tenantId, { integration_id: integrationId });
await admin.listPrincipalAuditEvents({ principal_id: principalId });

CarcRuntimeClient ​

The narrowest client — exactly two public methods, constructed with an integrationCredential (an opaque IntegrationCredentialBinding reference, never a management credential):

ts
import { CarcRuntimeClient } from "@giggle-ai/runtime-sdk";

const runtimeExec = new CarcRuntimeClient({
  baseUrl: process.env.CARC_RUNTIME_API_URL!,
  integrationCredential: process.env.CARC_INTEGRATION_CREDENTIAL!,
});

const result = await runtimeExec.executeRegisteredAgent("openai-discharge-summary-agent", {
  caseId: "case_demo_001",
  taskType: "discharge_summary",
  subjectType: "patient",
  subjectContext,
  sourceReferences,
  instructions: "Draft a discharge summary.",
});

runtimeExec.getLastCorrelationId();

A management credential presented here is rejected (credential_not_bound, 403) — never silently treated as "no credential presented". See Model Provider Adapters for the full managed- execution architecture this method drives, and Integration Governance & Identity for what must be true (active integration, active environment, active agent binding, active unexpired credential binding, current unexpired certification) before this call succeeds at all.

Examples in the monorepo ​

  • packages/runtime-sdk/examples/admin-principal-lifecycle.ts — a full CarcAdminClient walkthrough: create a principal, grant a tenant membership, issue/rotate/revoke a credential.
  • packages/runtime-sdk/examples/runtime-execute.ts — a CarcRuntimeClient walkthrough, including the credential_not_bound error path.
  • examples/quickstart-external-agent/ — the full Quickstart flow
  • examples/reference-integrations/ — three distinct end-to-end scenarios (see Reference Integrations)
  • examples/openai-clinical-agent/ — genuinely needs all three clients side by side (adapter reads, agent registry, and managed execution) — the concrete illustration of why they're separate classes, not one.

Developer Platform v1: Consequential Agent Runtime Control Platform