@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.
Installation
Choose your preferred package manager:
npm
npm install @hikigai/app-sdkyarn
yarn add @hikigai/app-sdkpnpm
pnpm add @hikigai/app-sdkQuick 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 contextCore 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 infoMCP 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}`)
}
}