Skip to content

Latest commit

 

History

History
201 lines (156 loc) · 9.49 KB

File metadata and controls

201 lines (156 loc) · 9.49 KB

@openhermit/sdk

TypeScript client for the OpenHermit gateway and agent APIs. Targets external integrations that need to provision agents, manage their configuration, and talk to live sessions over HTTP/WS without re-implementing the wire format.

npm install @openhermit/sdk
import { GatewayClient } from '@openhermit/sdk';

const gw = new GatewayClient({
  baseUrl: 'https://test.openhermit.ai',
  token: process.env.OPENHERMIT_ADMIN_TOKEN,
});

const agents = await gw.listAgents();

Auth model

There are two distinct caller identities. Pick the right token for each call:

  • Admin token — long-lived value from gateway config. Authorises every /api/admin/... route plus all per-agent CRUD. Use for back-office / server-to-server provisioning.
  • User JWT — issued either via POST /api/auth/token (device-key exchange) or GatewayClient.issueUserToken(...) (admin-minted on behalf of a user authenticated by your own system). Scoped to that user's agents.

GatewayClient accepts either as token. AgentClient (live session calls) expects a user JWT.

What the SDK supports today

GatewayClient — control plane

Auth / identity

  • GatewayClient.issueUserToken({ baseUrl, adminToken, channel, channelUserId, displayName?, purpose?, ttlSeconds? }) — admin-only mint of a user JWT for a (channel, channelUserId) identity. Use to bridge users authenticated by an external system into OpenHermit without device-key exchange.
    • purpose: 'session' (default) returns a normal 24h credential.
    • purpose: 'exchange' returns a single-use short-lived token (≤600s, default 120s) intended for the web /connect#token=… deep-link flow.
  • GatewayClient.exchangeConnectToken({ baseUrl, token }) — swap an exchange token for a 24h session JWT. The token is the credential (no admin token needed) and is rejected on a second redemption. Backs the /connect SSO flow described below.
  • GatewayClient.linkUserIdentity({ baseUrl, adminToken, userId, channel, channelUserId }) — admin-only: attach a (channel, channelUserId) pair to an existing user. Stitches identities together — e.g. when the same human has logged in via two channels and you want both pointing at one canonical user record. If the pair is already linked to a different user, the gateway reassigns it and prunes the orphan source user.

SSO deep link: /connect#token=…

For platforms that already authenticate their own users, the simplest way to drop them into the OpenHermit web UI is a short-lived exchange JWT:

  1. Server-side (on the trusted platform), mint an exchange token:
    const { token } = await GatewayClient.issueUserToken({
      baseUrl: 'https://hermit.example.com',
      adminToken: process.env.OPENHERMIT_ADMIN_TOKEN!,
      channel: 'my-platform',
      channelUserId: user.id,
      displayName: user.name,
      purpose: 'exchange',
    });
    const url = `https://hermit.example.com/connect?agent_id=${agentId}#token=${token}`;
  2. Redirect the user to url. The web app reads the token from the URL fragment (so it never hits the server log or referer), strips it, swaps it via POST /api/auth/exchange, and persists the resulting session JWT in localStorage.
  3. The exchange token is single-use — a replay (e.g. someone scraping the URL out of browser history) is rejected with 401.

The browser's existing device-key identity, if any, is left untouched so the same browser can hold both an SSO-issued identity and a device-key identity.

Catalog

  • listProviders(): ProviderCatalogEntry[] — provider/model snapshot from pi-ai.

Agents

  • listAgents() — admin: every agent in the fleet.
  • createAgent(request) / deleteAgent(agentId).
  • manageAgent(agentId, 'start' | 'stop' | 'restart' | 'enable' | 'disable').
  • agentHealth(agentId).

Per-agent config

  • getAgentConfig(agentId) / putAgentConfig(agentId, config).
  • getAgentSecurity(agentId) / putAgentSecurity(agentId, policy).

Secrets (per-agent, encrypted server-side)

  • getAgentSecrets(agentId) — returns masked previews + passThrough flags.
  • setAgentSecret(agentId, name, value, { passThrough? }).
  • deleteAgentSecret(agentId, name).

Channels (built-in adapters and external webhook channels)

  • listAgentChannels(agentId) — all channels with runtime status.
  • createExternalChannel(agentId, input) — returns the plaintext token once.
  • updateAgentChannel(agentId, channelId, input).
  • deleteAgentChannel(agentId, channelId).

Sandboxes (per-agent exec environments)

  • listSandboxes(agentId).
  • createSandbox(agentId, input).
  • deleteSandbox(agentId, alias).

Skills (admin)

  • listSkills() / scanSkills() / getSkill(...).
  • registerSkill(input) / deleteSkill(skillId).
  • listSkillAssignments() / enableSkill(skillId, agentId) / disableSkill(skillId, agentId).

MCP servers (admin)

  • listMcpServers() / registerMcpServer(input).
  • listMcpAssignments() / enableMcpServer(mcpServerId, agentId) / disableMcpServer(...).

Instructions (per-agent prompts)

  • listInstructions(agentId) / getInstruction(agentId, key).
  • setInstruction(agentId, key, content) / deleteInstruction(agentId, key).
  • fanoutInstruction(input) — admin: push the same key to many agents.

Schedules (per-agent crons)

  • listSchedules(agentId) / createSchedule(agentId, input).
  • updateSchedule(agentId, scheduleId, input) / deleteSchedule(agentId, scheduleId).
  • listScheduleRuns(agentId, scheduleId, limit?).

Policies (per-agent resource access)

  • listPolicies(agentId, resourceType?).
  • upsertPolicy(agentId, input) / deletePolicy(agentId, resourceType, resourceKey).

Approvals (per-agent tool-call approvals)

  • listApprovalRequests(agentId, status?) / getApprovalRequest(agentId, id).
  • reviewApprovalRequest(agentId, id, { decision, ... }).

Gateway-level config (admin)

  • getGatewayConfig() / putGatewayConfig(config).
  • getAdminStats().

AgentClient — runtime session

For talking to a running agent over HTTP/SSE/WS as a user.

  • openSession(spec) / listSessions(query?) / listSessionMessages(sessionId).
    • spec.customInstruction?: string — optional per-session prompt addendum. Stored once on the session row at create time and appended to the system prompt as a dedicated section after agent-level instructions. Immutable for the lifetime of the session (subsequent openSession calls for the same sessionId ignore the field).
  • postMessage(...) / appendMessage(...) — non-streaming.
  • postMessageSync(...) — wait for the assistant turn to complete.
  • postMessageStream(...) — async iterable of session events (SSE under the hood).
  • submitApproval(...) / checkpointSession(...).
  • reviewApprovalRequest(...) / reviewApprovalRequestByShortId(...).

AgentRealtimeClient — WebSocket client (chat-style consumers)

  • sessionOpen / sessionMessage / sessionApprove / sessionCheckpoint.
  • sessionList / sessionHistory.
  • subscribe(sessionId, lastEventId?) / unsubscribe(sessionId).

Not yet covered

The gateway exposes more routes than the SDK currently wraps. If you need any of these, drop a method in packages/sdk/src/index.ts matching the existing style. Prioritised by the hole they represent:

Multi-tenant / membership

  • POST /api/users — create users from outside the device-key flow.
  • GET /api/agents/:agentId/members — list users with access to an agent.
  • POST /api/agents/:agentId/members — share an agent with a user.
  • DELETE /api/agents/:agentId/members/:userId — revoke access.
  • POST /api/agents/:agentId/users/:userId/promote-to-owner.
  • GET /api/agents/:agentId/ownership / GET /api/agents/:agentId/info.
  • GET /api/users/me/agents — current-user's accessible agents (currently only listAgents() admin variant is wrapped).

Admin observability

  • GET /health, GET /metrics.
  • GET /api/admin/agents/fleet (admin fleet dashboard).
  • GET /api/admin/sandboxes (cross-agent sandbox view).
  • GET /api/admin/users / GET /api/admin/users/:userId/identities / GET /api/admin/users/:userId/agents.
  • GET /api/admin/logs (server log tail).
  • GET /api/admin/schedules (cross-agent schedule view).
  • GET /api/sandbox-presets (read-only catalog of sandbox templates).

Sessions / events

  • DELETE /api/agents/:agentId/sessions/:sessionId — delete a session.
  • GET /api/agents/:agentId/sessions/:sessionId/events — raw SSE event stream (AgentClient.postMessageStream covers the message-driven case but not arbitrary subscription).

Channels

  • POST /api/agents/:agentId/channels/:namespace/webhook — inbound webhook delivery. External integrations call this directly with the token from createExternalChannel; the SDK currently doesn't wrap it because typical consumers are receiving webhooks, not posting them programmatically.

Schedules

  • POST /api/agents/:agentId/schedules/:scheduleId/trigger — manual fire of a cron entry (useful for "test run now" buttons).

Approvals

  • POST /api/agents/:agentId/approvals/by-short/:shortId/review — review by short-id (the long-id form is wrapped).

Versioning

Semver-ish. Additive methods are minor/patch bumps; type-breaking changes are minor (we're pre-1.0). The ESM build is published from dist/; the development export condition is stripped at pack time via prepack so in-monorepo dev keeps reading src/ directly without polluting the published tarball.

See packages/sdk/src/index.ts for the authoritative type surface.