Hikigai

@hikigai/app-sdk

Application SDK

Official Node.js SDK for invoking healthcare AI agents in your applications. Full streaming, WebSocket, and session support with type-safe responses.

v0.1.0Node.js 18+StreamingWebSocket

Installation

Choose your preferred package manager:

npm

npm install @hikigai/app-sdk

yarn

yarn add @hikigai/app-sdk

pnpm

pnpm add @hikigai/app-sdk

Quick Start

import { AppClient } from '@hikigai/app-sdk'

// Initialize client
const client = new AppClient({
  apiKey: process.env.HIKIGAI_API_KEY,
  projectId: process.env.HIKIGAI_PROJECT_ID,
})

// Get an agent
const agent = await client.agent('medical-coder')

// Basic invocation
const response = await agent.invoke('Patient presents with fever and cough...')
console.log(response.content)

// Streaming responses
for await (const chunk of agent.stream('Tell me about type-2 diabetes')) {
  process.stdout.write(chunk)
}

// Session-based conversations
const sessionAgent = agent.withSession('patient-123')
await sessionAgent.invoke('What is the treatment?')
await sessionAgent.invoke('Any contraindications?') // Remembers context

Core Concepts

AppClient

Main interface for agent invocation and management.

class AppClient {
  constructor(options?: {
    apiKey?: string          // API key (or HIKIGAI_API_KEY env var)
    projectId?: string       // Project ID (or HIKIGAI_PROJECT_ID env var)
    baseUrl?: string         // API endpoint
    timeout?: number         // Request timeout in milliseconds
  })

  async agent(agentId: string): Promise<RuntimeAgent>
  async listAgents(): Promise<RuntimeAgent[]>
  sona: SONAClient                  // SONA personalization
}

RuntimeAgent

Represents a deployed agent ready for invocation.

interface RuntimeAgent {
  id: string
  name: string
  slug: string
  version?: string
  description?: string
  status: 'active' | 'pending' | string
  endpoint?: string

  // Methods
  invoke(input: string | Record<string, unknown>, 
    options?: InvokeOptions): Promise<InvokeResponse>
  
  stream(input: string | Record<string, unknown>,
    options?: StreamOptions): AsyncIterable<string>
  
  withSession(sessionId: string): RuntimeAgent
  
  liveSession(): StreamSession
}

Invocation Methods

Multiple ways to interact with agents.

Basic Invocation

const response = await agent.invoke(
  'Clinical note to analyze',
  {
    sessionId: 'patient-123',
    timeout: 60000,
  }
)

console.log(response.content)           // Agent response
console.log(response.metadata.latencyMs) // Performance info

MCP Connectors

Pass linked MCP connector slugs in connectors. The platform injects apiKey and projectId from your AppClient credentials automatically.

import type { McpConnectors } from '@hikigai/app-sdk'

const connectors: McpConnectors = {
  'idexx-mcp-server': {},  // platform auth injected automatically
}

const response = await agent.invoke('Prepare patient chart', { connectors })

// Optional HTTP headers (Claude Desktop style)
const withHeaders: McpConnectors = {
  'idexx-mcp-server': {
    headers: {
      'X-API-Key': process.env.HIKIGAI_API_KEY!,
      'X-Project-Id': process.env.HIKIGAI_PROJECT_ID!,
    },
  },
}

Agent Discovery

// Get specific agent
const agent = await client.agent('medical-coder')

// List all agents
const agents = await client.listAgents()

// Search agents
const filtered = await client.listAgents({
  category: 'medical-coding',
  tags: ['icd-10'],
  search: 'coding',
})

Streaming Responses

Process responses in real-time as they arrive.

// Stream text responses
for await (const chunk of agent.stream('Analyze this report...')) {
  process.stdout.write(chunk)
}

// Collect streamed data
let fullResponse = ''
for await (const chunk of agent.stream(input)) {
  fullResponse += chunk
}

console.log('Complete response:', fullResponse)

Session Management

Multi-turn conversations with persistent context.

const sessionAgent = agent.withSession('patient-789')

// First turn - establish context
await sessionAgent.invoke('I have been experiencing chest pain')

// Second turn - knows about chest pain
await sessionAgent.invoke('Is this serious?')

// Third turn - maintains full conversation history
await sessionAgent.invoke('What tests should I get?')

WebSocket Live Sessions

Real-time bidirectional communication with agents.

const session = agent.liveSession()

// Connect to agent
await session.connect()

// Send messages
await session.sendText('Hello, I need help')

// Receive events
for await (const event of session) {
  if (event.type === 'text') {
    console.log('Agent:', event.content)
  } else if (event.type === 'thinking') {
    console.log('Agent thinking...')
  } else if (event.type === 'error') {
    console.error('Error:', event.error)
  }
}

// Clean up
await session.close()

Response Models

interface InvokeResponse {
  content: string                     // Main response text
  agentId: string                     // Agent ID
  agentVersion?: string              // Version used
  sessionId?: string                 // Session ID
  metadata: InvocationMetadata       // Metadata
  plugins?: Record<string, Record<string, unknown>>  // Plugin responses
}

interface InvocationMetadata {
  invocationId: string               // Unique ID
  latencyMs: number                  // Response time
  timestamp: string                  // ISO timestamp
  status: 'success' | 'error'        // Status
  tokensUsed?: number                // Token count
  toolsCalled?: string[]             // Tools used
  clinicalConfidence?: {
    score: number                    // 0-100
    reasoning?: string
  }
  safetyFlags?: Array<{
    type: string
    severity: 'info' | 'warning' | 'error'
    message: string
  }>
}

End-User Identity

Add signup, login, MFA, QR badge login, and SSO for your app's end users. Each app is backed by a dedicated AWS Cognito pool the platform provisions for you; login returns standard OIDC tokens. Reach it all through client.identity.

IdentityClient

interface IdentityClient {
  // Accounts & auth
  signup(appId: string, email: string, password: string,
    opts?: { displayName?: string; attributes?: Record<string, string> }): Promise<Record<string, unknown>>
  confirm(appId: string, email: string, code: string): Promise<Record<string, unknown>>
  login(appId: string, email: string, password: string): Promise<TokenResult>
  refresh(appId: string, refreshToken: string): Promise<TokenResult>
  logout(appId: string, email: string): Promise<Record<string, unknown>>
  listAppUsers(appId: string, opts?: { limit?: number; offset?: number }): Promise<Record<string, unknown>[]>
  deleteAppUser(appId: string, email: string): Promise<void>

  // MFA (TOTP)
  mfaAssociate(appId: string, accessToken: string): Promise<Record<string, unknown>>
  mfaVerify(appId: string, accessToken: string, code: string, opts?: { deviceName?: string }): Promise<Record<string, unknown>>
  mfaSetPreference(appId: string, accessToken: string, opts?: { enabled?: boolean }): Promise<Record<string, unknown>>
  mfaRespond(appId: string, email: string, session: string, code: string): Promise<TokenResult>

  // QR badge & SSO
  issueQrLogin(appId: string, email: string): Promise<Record<string, unknown>>
  qrLogin(appId: string, qrPayload: string): Promise<TokenResult>
  configureSso(appId: string, opts: { providerName: string; providerType: string; /* ... */ }): Promise<Record<string, unknown>>
  ssoAuthorizeUrl(appId: string, redirectUri: string, opts?: { provider?: string }): Promise<Record<string, unknown>>
  ssoExchange(appId: string, code: string, redirectUri: string): Promise<TokenResult>

  // Setup (one-time, per app)
  enableIdentity(appId: string, opts?: { mode?: string; enabledMethods?: string[] }): Promise<Record<string, unknown>>
  getIdentityConfig(appId: string): Promise<Record<string, unknown>>
  byoSetup(): Promise<Record<string, unknown>>
  byoTest(roleArn: string, opts?: { region?: string }): Promise<Record<string, unknown>>
}

Sign up, confirm, log in

import { AppClient } from '@hikigai/app-sdk'

const client = new AppClient({ apiKey: process.env.HIKIGAI_API_KEY })

// 1. Register the end user
await client.identity.signup('app_123', 'clinician@hospital.com', 'Temp#Pass2026', {
  displayName: 'Dr. Mehta',
  attributes: { role: 'clinician' },
})

// 2. Confirm (skip if the pool auto-confirms)
await client.identity.confirm('app_123', 'clinician@hospital.com', '123456')

// 3. Log in -> OIDC tokens
const tokens = await client.identity.login('app_123', 'clinician@hospital.com', 'Temp#Pass2026')
console.log(tokens.accessToken)

Multi-factor login

const result = await client.identity.login('app_123', 'clinician@hospital.com', 'Temp#Pass2026')

if (result.status === 'challenge') {
  const code = await promptForTotpCode()
  const tokens = await client.identity.mfaRespond(
    'app_123', 'clinician@hospital.com', result.session!, code,
  )
  console.log(tokens.accessToken)
}

QR badge login

// Admin: issue a badge for the user (payload shown once)
const badge = await client.identity.issueQrLogin('app_123', 'clinician@hospital.com')
console.log(badge.qr_payload)   // encode into the printed badge

// Kiosk: scan the badge, exchange it for tokens
const tokens = await client.identity.qrLogin('app_123', scannedPayload)

Complete Example

import { AppClient } from '@hikigai/app-sdk'

const client = new AppClient()

async function clinicalWorkflow() {
  const diagnosisAgent = await client.agent('diagnosis-assistant')
  const codingAgent = await client.agent('clinical-coder')

  const sessionId = 'patient-dr-smith-2026'

  // Initial assessment
  const assessment = await diagnosisAgent.invoke(
    'Fever 38.5°C, cough, shortness of breath for 3 days',
    { sessionId }
  )
  console.log('Assessment:', assessment.content)

  // Follow-up question - remembers context
  const followUp = await diagnosisAgent.invoke(
    'Any chest pain or sputum production?',
    { sessionId }
  )
  console.log('Follow-up:', followUp.content)

  // Extract medical codes
  const coding = await codingAgent.invoke(assessment.content)
  console.log('Codes:', coding.content)

  // Stream treatment plan
  for await (const chunk of diagnosisAgent.stream(
    'What is the recommended treatment?',
    { sessionId }
  )) {
    process.stdout.write(chunk)
  }
}

Error Handling

import {
  HikigaiError,
  AuthenticationError,
  RateLimitError,
  AgentNotFoundError,
  InvocationError,
} from '@hikigai/app-sdk'

try {
  const response = await agent.invoke('...')
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Invalid credentials')
  } else if (error instanceof RateLimitError) {
    console.error(`Rate limited. Retry after ${error.retryAfter}ms`)
  } else if (error instanceof AgentNotFoundError) {
    console.error('Agent not found')
  } else if (error instanceof InvocationError) {
    console.error(`Invocation failed: ${error.message}`)
  } else if (error instanceof HikigaiError) {
    console.error(`API error: ${error.message}`)
  }
}