Hikigai

AgentSDK

Agent Deployment SDK

Deploy and manage healthcare AI agents for medical coding, clinical documentation, and diagnosis assistance. Built for HIPAA-compliant medical applications with clinical schemas and medical tools. Perfect for healthcare ML engineers and medical agent developers.

v0.3.3Python 3.10+Type HintsHIPAA ReadyJobs & Rooms

Installation

Using pip

pip install hikigai-agentsdk

Quick Start

from hikigai.agentsdk import AgentClient, AgentConfig
from hikigai.agentsdk import InputSchema, OutputSchema, StringField

# Initialize client (or set HIKIGAI_API_KEY / HIKIGAI_PROJECT_ID)
client = AgentClient(
    api_key="your-api-key",
    project_id="your-project-id",
    base_url="https://backend.hikigaiplatform.io",
)

agent = client.deploy(AgentConfig(
    name="medical-summarizer",
    display_name="Clinical Note Summarizer",
    description="Summarizes clinical notes into SOAP format",
    instruction="You are a clinical assistant. Summarize the input into SOAP format.",
    model="claude-3.5-sonnet",
    category="documentation",
    version="1.0.0",
    timeout=60,
    memory_mb=512,
    input_schema=InputSchema(fields={"note": StringField(required=True)}),
    output_schema=OutputSchema(fields={"summary": StringField()}),
))

print(f"Agent deployed: {agent.id} ({agent.slug})")

# Dev helpers — pass a string or a dict matching input_schema
result = client.invoke(agent.id, {"note": "Patient presents with fever and cough."})
print(result)

for chunk in client.stream(agent.id, {"note": "Patient presents with fever and cough."}):
    print(chunk, end="")

Client Reference

class AgentClient

AgentClientCore

Main interface for agent deployment and management. Handles API communication, authentication, and agent lifecycle operations.

Constructor

client = AgentClient(
    api_key: Optional[str] = None,        # API key (or HIKIGAI_API_KEY env var)
    project_id: Optional[str] = None,     # Project ID (or HIKIGAI_PROJECT_ID env var)
    base_url: Optional[str] = None,       # API endpoint (defaults to production)
    timeout: float = 30.0,                # Request timeout in seconds
)

Methods

MethodReturnsDescription
deploy(config, timeout=1200.0, poll_interval=10.0)DeployedAgentDeploy a new agent and poll until active
list_agents()List[DeployedAgent]List all deployed agents
get_agent(agent_id: str)DeployedAgentGet agent by ID or slug
update_agent(agent_id: str, update: Dict)DeployedAgentUpdate agent metadata/config and trigger redeploy
delete_agent(agent_id: str)NoneDelete an agent
invoke(agent_id, input, session_id=None, provider=None, model=None)Dict[str, Any]Invoke a deployed agent (dev/test helper)
stream(agent_id, input, session_id=None, provider=None, model=None)Iterator[str]SSE stream chunks from a deployed agent
get_auth_token()Dict[str, Any]Exchange API key for a short-lived access token

Properties

jobs()JobsClientBackground job queue (enqueue, wait, stream, cancel, replay)
storage()StorageClientApp object storage (upload, signed_url, list, get, delete)

Context Manager

with AgentClient() as client:
    agent = client.deploy(config)
# Resources automatically released

class JobsClient (client.jobs)

client.jobsJobs

Background job queue for long-running agent work. Access via AgentClient.jobs.

MethodReturnsDescription
enqueue(job_type, payload, agent_id=None, priority='standard', ...)EnqueuedJobEnqueue a background job
get(job_id: str)JobDetailFetch job status and result
list(status=None, job_type=None, agent_id=None, page=1, per_page=20)List[JobDetail]List jobs with filters
cancel(job_id: str)JobDetailCancel a queued or running job
replay(job_id, override_retry_policy=None, override_payload=None)EnqueuedJobRe-enqueue a failed job
wait(job_id, timeout=600.0, poll_interval=5.0)JobDetailBlock until the job reaches a terminal status
stream(job_id: str)Iterator[Dict]Stream live job progress events
job = client.jobs.enqueue(
    "agent.invoke",
    {"input": "Batch-code these notes"},
    agent_id=agent.id,
    priority="standard",
)
detail = client.jobs.wait(job.id)
print(detail.status, detail.result)

Storage (client.storage)

client.storageStorage

Platform-managed object storage for app files (PDFs, images, audio, attachments). Objects are scoped to a project + app_id. Upload returns a short-lived signed URL; mint a fresh one with signed_url() when you need to download later.

Methods

MethodReturnsDescription
upload(app_id, file, filename, content_type='application/octet-stream', metadata=None, ttl=None)StorageUploadResultMultipart upload. Optional metadata (JSON) and object TTL in seconds. Result includes object_id and a signed_url (~1h).
signed_url(app_id, object_id, ttl=3600)SignedUrlResultMint a temporary download URL (signed_url, expires_in, expires_at)
list(app_id, content_type=None, status='active', limit=20, page=1)StorageListResultPaginated list; filter by content_type and status
get(app_id, object_id)StorageObjectInfoFetch metadata for one object (filename, size, status, metadata, …)
delete(app_id, object_id)NoneDelete an object

Return shapes

StorageUploadResultdataclassobject_id, object_key, original_filename, content_type, size_bytes, signed_url, expires_at, created_at
SignedUrlResultdataclassobject_id, signed_url, expires_in, expires_at
StorageObjectInfodataclassobject_id, original_filename, content_type, size_bytes, metadata, status, upload_source, expires_at, created_at
StorageListResultdataclassobjects, total, page, limit, total_pages

Example

# Upload with metadata + optional object TTL
with open("note.pdf", "rb") as f:
    uploaded = client.storage.upload(
        app_id="app_123",
        file=f,
        filename="note.pdf",
        content_type="application/pdf",
        metadata={"visit_id": "v-42", "kind": "clinical-note"},
        ttl=86400,  # object expires in 24h (optional)
    )
print(uploaded.object_id, uploaded.size_bytes, uploaded.signed_url)

# Fresh download URL later
url = client.storage.signed_url("app_123", uploaded.object_id, ttl=3600)
print(url.signed_url, url.expires_at)

# Inspect one object
info = client.storage.get("app_123", uploaded.object_id)
print(info.original_filename, info.metadata, info.status)

# List with filters / pagination
page = client.storage.list(
    "app_123",
    content_type="application/pdf",
    status="active",
    limit=20,
    page=1,
)
for obj in page.objects:
    print(obj.object_id, obj.original_filename, obj.size_bytes)
print(page.total, page.total_pages)

client.storage.delete("app_123", uploaded.object_id)

class RoomSession

RoomSessionRealtime

Create and use multi-party realtime rooms from the SDK — join, publish, presence, and optional WebRTC signalling. Standalone class (not on AgentClient). Requires the optional websockets package.

Use RoomSession to open a room session, then join(name) — the first join creates the room in your project (no separate create step). From there you can publish, listen for frames, and optionally negotiate WebRTC with the rtc_* helpers.

Constructor

from hikigai.agentsdk import RoomSession

room = RoomSession(
    base_url="https://backend.hikigaiplatform.io",  # required
    api_key="hikigai_...",      # or access_token=... or room_token=...
    project_id="your-project-id",
)
ParamTypeDescription
base_url*strPlatform base URL (same as AgentClient); RoomSession opens the rooms WebSocket from this
api_keystr | NoneProject API key — full subscribe/publish/manage/rtc for that project
access_tokenstr | NoneShort-lived JWT (e.g. from AgentClient.get_auth_token())
room_tokenstr | NoneEnd-user room token with scoped rooms + capabilities
project_idstr | NoneRequired with api_key / access_token for project namespace

Auth: pass exactly one of api_key, access_token, or room_token. API-key / JWT principals get all capabilities on their project's rooms.room_token principals get only the rooms/capabilities minted into the token (default subscribe + publish; request rtc or manage explicitly).

Properties

connection_idstr | NoneServer-assigned connection id after auth
capabilitiesList[str]Granted caps after ready (subscribe, publish, manage, rtc)
last_seqDict[str, int]Per-room last delivered message seq (used on reconnect)

Methods

MethodReturnsDescription
connect()NoneOpen WS, send auth, wait for ready
close()NoneSend disconnect and close the socket
reconnect()NoneReopen + rejoin all rooms with last_seq; re-announce RTC peers
join(room, last_seq=None)DictCreate (if new) or join a room; optional seq for replay
leave(room)NoneLeave room (also drops RTC peer if any)
publish(room, event, data=None, *, echo=False)NoneBroadcast an event; echo=True also delivers to sender
who(room)NoneRequest member list; reply arrives on the iterator
ping()NoneKeepalive ping
refresh(room_token)NoneRotate room_token in-place without reconnecting
rtc_join(room, *, mode=None, agent_id=None, metadata=None)DictAnnounce as WebRTC peer (requires rtc capability + prior join)
rtc_leave(room)NoneLeave RTC session but stay a room member
rtc_offer(room, target, sdp)NoneSend SDP offer to one peer
rtc_answer(room, target, sdp)NoneAnswer one peer's offer
rtc_candidate(room, target, candidate)NoneTrickle ICE candidate (RTCIceCandidateInit shape)
rtc_who(room)NoneRequest current RTC peer list

Inbound frames (async for frame in room)

typeMeaning
joinedJoin ack + your capabilities + members
messagePublished event (room, event, data, seq, ts)
presenceMembers joined/left
errorNormative code (unauthorized, forbidden, room_full, cursor_expired, …)
rtc_joined / rtc_peer_joined / rtc_peer_leftRTC peer lifecycle + ice_servers
rtc_offer / rtc_answer / rtc_candidateDirected SDP/ICE signalling (media is peer-to-peer)

Reconnect & delivery

  • Default delivery is at-most-once. The client tracks last_seq per room and dedupes replays.
  • reconnect() rejoins with last_seq so the server can replay the gap.
  • If you get cursor_expired, the gap outgrew the replay buffer — resync app state from scratch.
  • Room names: 1–128 chars of letters, digits, _ . : -.

To mint a scoped end-user room_token or publish from a backend without a socket, see API reference → Rooms. Day-to-day create / join / publish is all on RoomSession.

Example — create, join, publish

import asyncio
from hikigai.agentsdk import RoomSession

async def main():
    room = RoomSession(
        base_url="https://backend.hikigaiplatform.io",
        api_key="your-api-key",
        project_id="your-project-id",
    )
    async with room:
        await room.join("rounds-42")
        await room.publish("rounds-42", "update", {"status": "in_progress"})
        await room.who("rounds-42")
        async for frame in room:
            if frame.get("type") == "message":
                print(frame["event"], frame["data"], frame.get("seq"))
            elif frame.get("type") == "error":
                print("error", frame.get("code"), frame.get("message"))
                break

asyncio.run(main())

Example — WebRTC signalling

Signalling only — plug frames into aiortc / RTCPeerConnection. Details: API reference → WebRTC.

await room.join("call-1")
await room.rtc_join("call-1")  # rtc_joined arrives on the iterator (ice_servers, peers)
async for frame in room:
    if frame["type"] == "rtc_peer_joined" and frame.get("initiator"):
        await room.rtc_offer("call-1", frame["id"], await make_offer())
    elif frame["type"] == "rtc_offer":
        await room.rtc_answer("call-1", frame["sender"], await answer(frame["sdp"]))
    elif frame["type"] == "rtc_candidate":
        await add_ice(frame["sender"], frame["candidate"])

Configuration Reference

class AgentConfig

AgentConfigPydantic Model

Comprehensive configuration for deploying an agent. Supports schemas, tools, versioning, and HIPAA compliance.

PropertyTypeDescription
Identity
name*strUnique agent name (3-64 chars, lowercase, hyphens)
display_name*strHuman-readable display name (3-100 chars)
description*strShort description (10-500 chars)
long_descriptionstr | NoneFull documentation (max 5000 chars)
Core
agent_typestrOrchestration: llm (single), sequential, parallel, or loop — see Workflow Agents
Default: llm
instruction*strSystem prompt/instruction (10-50,000 chars)
modelstrLLM model to use
Default: claude-3.5-sonnet
Multi-Agent Support
sub_agentsList[SubAgentConfig]Nested leaves for sequential/parallel/loop roots
Default: []
Advanced Features
planner_configPlannerConfig | NoneEnable planning/reasoning capabilities
code_executionboolEnable code execution capability
Default: False
generation_configGenerationConfig | NoneLLM generation parameters
State Management
output_keystr | NoneKey to save agent output in state for downstream agents
include_contentsstr | NoneControl conversation history inclusion
max_iterationsint | NoneMaximum iterations for LoopAgent
Classification
categorystrCategory from predefined list
Default: documentation
tagsList[str]Tags for discovery (max 10)
Default: []
Schemas
input_schema*InputSchema | DictInput data structure definition
output_schema*OutputSchema | DictOutput data structure definition
Modality
input_modalitystrInput modality: text, audio, image, video, document, or combinations
Default: text
output_modalitystrOutput modality: text, audio, image, document, or combinations
Default: text
vadVadConfig | NoneLive automatic VAD (applied only when input_modality includes audio). Defaults: silence 800ms, sensitivities low/low
Tools & Connectors
toolsList[Any]Tools available to the agent
Default: []
connectorsList[ConnectorConfig]Root MCP connectors — attached at invoke/live to every LlmAgent leaf (Sequential/Parallel/Loop), not only a simple LLM root
Default: []
Runtime
timeoutintRequest timeout in seconds (5-300)
Default: 60
memory_mbintMemory allocation in MB (128-4096)
Default: 512
min_instancesintMinimum scaling instances (0-10)
Default: 0
max_instancesintMaximum scaling instances (1-100)
Default: 10
Versioning
version*strSemantic version (e.g., '1.0.0')
changelogstr | NoneWhat changed in this version
Compliance & Visibility
hipaa_compliantboolAgent handles PHI per HIPAA
Default: True
publicboolPublicly listed in marketplace
Default: False
Cloud Deployment
cloud_providerstr | NoneAllowed values: 'gcp' or 'aws'. Omit to use the org/project default cloud account (Organization settings → Cloud accounts, or a project override).
cloud_credential_namestr | NoneOptional Cloud accounts name. Omit to use the org/project default account.
gcp_regionstrGCP region for deployment
Default: us-central1
aws_regionstrAWS region for deployment
Default: us-east-1
Healthcare Spec
risk_tierstr | NoneHealthcare risk tier
Default: low
clinical_domainstr | NoneClinical domain category
a2a_skillsList[Dict]Machine-readable capabilities for AI-to-AI discovery
Default: []
resource_limitsDict[str, str]Container resource limits
Default: {'cpu': '1', 'memory': '512Mi'}
fhir_resourcesList[Dict]Required FHIR resources for agent operation
Default: []
prompt_versionstr | NoneSpecific version of the clinical prompt
Default: 1.0.0
requires_physician_oversightboolDoes this agent require human physician sign-off?
Default: False
fda_clearance_statusstrFDA clearance status
Default: not-applicable

Example

config = AgentConfig(
    name="medical-coder",
    display_name="Medical Coding Assistant",
    description="Extracts ICD-10 codes from clinical notes",
    instruction="You are a medical coding expert...",
    model="claude-3.5-sonnet",
    category="coding-billing",
    tags=["icd-10", "healthcare"],
    input_schema=InputSchema(fields={"note": StringField(required=True)}),
    output_schema=OutputSchema(fields={"codes": ArrayField()}),
    timeout=60,
    memory_mb=512,
    version="1.0.0",
    hipaa_compliant=True
)

class VadConfig

VadConfigPydantic Model

Automatic voice activity detection for live audio agents (Gemini Live realtime_input_config). Applied only when input_modality includes audio.

PropertyTypeDescription
silence_duration_msint | NoneSilence in ms before the user turn is committed (200–2000)
Default: 800
end_of_speech_sensitivitystr | None'high' commits sooner after a pause; 'low' waits longer
Default: low
start_of_speech_sensitivitystr | None'high' starts capturing sooner; 'low' is less sensitive
Default: low

Example

from hikigai.agentsdk import AgentConfig, VadConfig

agent = client.deploy(AgentConfig(
    ...,
    input_modality="audio",
    output_modality="text",
    vad=VadConfig(
        silence_duration_ms=800,              # or override, e.g. 300
        end_of_speech_sensitivity="low",
        start_of_speech_sensitivity="low",
    ),
))

# Defaults when constructing VadConfig():
#   silence_duration_ms=800, sensitivities="low" / "low"

Include vad on every same-name deploy() if you want to keep or change VAD. Prefer a full config redeploy over update_agent for modality/VAD changes.

Schema Types

InputSchema & OutputSchemaPydantic Model

Define the structure of data your agent expects and returns.

from hikigai.agentsdk import InputSchema, OutputSchema, StringField, IntegerField

input_schema = InputSchema(
    description="Patient information",
    fields={
        "patient_id": StringField(required=True),
        "age": IntegerField(required=True, minimum=0, maximum=150),
    }
)

output_schema = OutputSchema(
    description="Diagnosis results",
    fields={
        "diagnosis": StringField(),
        "confidence": IntegerField(minimum=0, maximum=100),
    }
)

Field Types

StringField

StringField(
    required=True,
    description="Field description",
    min_length=1,
    max_length=1000,
    pattern=r"^[A-Z0-9-]+$",
    enum=["option1", "option2"]
)

IntegerField

IntegerField(
    required=True,
    minimum=0,
    maximum=100,
    default=50
)

BooleanField

BooleanField(
    required=False,
    default=False
)

ArrayField

ArrayField(
    items=StringField(),
    min_items=1,
    max_items=10
)

ObjectField

ObjectField(
    properties={
        "name": StringField(),
        "value": IntegerField()
    },
    required_fields=["name"]
)

Workflow Agents (Sequential / Parallel / Loop)

Set agent_type to sequential, parallel, or loop and pass nested sub_agents. Text workflows advance automatically under run_async. Live (/live) workflows need leaf handoff — see live_handoff below. After deploy, open a live session with AppSDK live().

TypeBehaviorLive notes
sequentialLeaves run one after anotherShared mic; advance via task_completed or after_output
parallelLeaves run concurrentlyMic teed to all branches; prefer text-only outs to avoid audio clash
loopRepeats leaf sequence until escalate / max_iterationsSame leaf handoff rules as sequential

class SubAgentConfig

SubAgentConfigPydantic Model

One leaf (or nested workflow) under a Sequential, Parallel, or Loop root. Define your own leaf with instruction/model, or reuse a marketplace agent by name.

name*strLeaf name (letters, numbers, hyphens, underscores). For marketplace reuse, use the marketplace agent name/slug.
agent_typestrllm (default) or nested sequential/parallel/loop. Not required for marketplace reuse.
Default: llm
modelstr | NoneModel for this leaf. Required for your own agents; omitted when source='marketplace' (loaded from the source agent).
instructionstr | NoneLeaf system prompt. Required for your own agents (min 10 chars). Omit when source='marketplace' — the platform hydrates it.
descriptionstr | NoneShort description (own agents). Optional display metadata for marketplace reuse.
sourceLiteral["marketplace"] | NoneSet to 'marketplace' to reuse an existing marketplace agent by name/slug. Do not pass instruction/model/schemas — the platform resolves and hydrates them.
source_agent_idstr | NoneOptional explicit agent UUID to reuse (project-owned or marketplace-linked). Alternative to source='marketplace' + name.
input_schemadict | NoneOptional leaf input schema (own agents). Hydrated automatically for marketplace reuse.
output_schemadict | NoneOptional leaf output schema (own agents). Hydrated automatically for marketplace reuse.
input_modalitystrtext, audio, or combinations
Default: text
output_modalitystrtext, audio, or combinations
Default: text
live_handoffLiteral["task_completed","after_output"]How this leaf ends under live Sequential/Loop/Parallel. Default task_completed = multi-turn until tool. after_output = one-shot (turn_complete or short idle). Ignored for simple live LlmAgent roots and for non-live text workflows.
Default: task_completed
toolsList[str]Tool names for this leaf
Default: []
sub_agentsList[SubAgentConfig]Nested children when agent_type is a workflow
Default: []
max_iterationsint | NoneLoopAgent only

Own agent vs marketplace reuse: If you pass instruction (and usually model), the leaf is your own. If you set source="marketplace" with a name, the platform looks up that marketplace agent and fills instruction, model, and schemas at deploy time.

from hikigai.agentsdk import AgentClient, AgentConfig, SubAgentConfig
from hikigai.agentsdk import InputSchema, OutputSchema, StringField

client = AgentClient()  # HIKIGAI_API_KEY + HIKIGAI_PROJECT_ID

config = AgentConfig(
    name="cpt2-note-workflow",
    display_name="CPT2 Note Workflow",
    description="Clean a clinical note, then reuse CPT2 from the marketplace",
    agent_type="sequential",
    model="gemini-2.5-flash",
    instruction="Pass the note through prep, then CPT Category II extraction.",
    version="1.0.0",
    category="coding-billing",
    input_schema=InputSchema(fields={"input": StringField(description="Clinical note")}),
    output_schema=OutputSchema(fields={"output": StringField(description="Coding result")}),
    sub_agents=[
        # Your own sub-agent — full instruction / schemas
        SubAgentConfig(
            name="note_cleaner",
            model="gemini-2.5-flash",
            instruction="Clean and structure the note for CPT II coding. Do not invent facts.",
            description="Prepares notes for coding",
            input_schema=InputSchema(fields={"input": StringField()}),
            output_schema=OutputSchema(fields={"output": StringField()}),
        ),
        # Marketplace reuse — name + source only (no id / instruction / schemas)
        SubAgentConfig(
            name="cpt2_code_agent",  # marketplace name or slug
            source="marketplace",
        ),
    ],
)

agent = client.deploy(config)
# Invoke with AppSDK: AppClient().agent(agent.slug).invoke({"input": "..."})

live_handoff explained

  • task_completed (default) — stay on the leaf until it calls the task_completed tool. Use for multi-turn conversation leaves.
  • after_output — advance after the model produces output and the turn completes (or stalls briefly). Use for one-shot pipeline leaves (STT, extract, compose). Native-audio models often narrate tools instead of calling them.
  • Simple bidirectional agents (plain LlmAgent live roots) never use this flag.
  • Normal text Sequential/Parallel/Loop (non-live) advance on their own — no handoff flag needed.
from hikigai.agentsdk import AgentClient, AgentConfig, SubAgentConfig

client = AgentClient(api_key="...", project_id="...")

config = AgentConfig(
    name="clinical-live-pipeline",
    display_name="Clinical Live Pipeline",
    description="Sequential live intake with one-shot leaves",
    agent_type="sequential",
    model="gemini-2.5-flash-native-audio-preview-12-2025",
    instruction="Orchestrate the live clinical pipeline.",
    version="1.0.0",
    input_modality="audio",
    output_modality="audio",
    input_schema={"type": "object", "properties": {"audio": {"type": "string"}}},
    output_schema={"type": "object", "properties": {"note": {"type": "string"}}},
    sub_agents=[
        SubAgentConfig(
            name="voice-intake",
            model="gemini-2.5-flash-native-audio-preview-12-2025",
            instruction="Wait for the user, then acknowledge in under 8 words.",
            input_modality="audio",
            output_modality="audio",
            live_handoff="after_output",
        ),
        SubAgentConfig(
            name="note-composer",
            model="gemini-2.5-flash-native-audio-preview-12-2025",
            instruction="Emit a short SOAP note from context, then stop.",
            input_modality="text",
            output_modality="text",
            live_handoff="after_output",
        ),
    ],
)

agent = client.deploy(config)
# Then open /live with AppSDK:
#   async with AppClient(...).live(agent.slug) as session: ...

MCP on Sub-Agents

Declare connectors on the root AgentConfig. At invoke/live the platform attaches those MCP tools to every LlmAgent in the tree — the simple root and each Sequential / Parallel / Loop leaf — so workflow sub-agents can CallTool. Parallel leaves get isolated toolsets. Prefer declaring connectors at deploy so leaf output_schema is not baked onto LlmAgents (ADK skips CallTool when schema is set). Auth still comes from AppSDK connectors={...}.

from hikigai.agentsdk import (
    AgentClient, AgentConfig, ConnectorConfig, SubAgentConfig,
    InputSchema, OutputSchema, StringField, IntegerField,
)

client = AgentClient(api_key="...", project_id="...")

config = AgentConfig(
    name="vitals-fetch-subagent",
    display_name="Vitals Fetch (Subagent MCP)",
    description="Sequential: MCP fetch leaf, then summarizer",
    instruction="Run fetcher then summarizer. Do not answer yourself.",
    model="gemini-2.5-flash",
    agent_type="sequential",
    category="monitoring",
    version="1.0.0",
    # Root connectors → every leaf can CallTool
    connectors=[
        ConnectorConfig(
            slug="idexx-mcp-server",
            tool_filter=["get_vitals_for_today"],
            required=True,
        ),
    ],
    sub_agents=[
        SubAgentConfig(
            name="vitals-fetcher",
            model="gemini-2.5-flash",
            instruction="Call get_vitals_for_today once with site_id and patient_id.",
        ),
        SubAgentConfig(
            name="vitals-summarizer",
            model="gemini-2.5-flash",
            instruction='Emit {"response": "<summary>"}. Do not call tools.',
        ),
    ],
    input_schema=InputSchema(fields={
        "site_id": IntegerField(required=True),
        "patient_id": StringField(required=True),
    }),
    output_schema=OutputSchema(fields={
        "response": StringField(required=True),
    }),
)

agent = client.deploy(config)
# Invoke with AppSDK — see /docs/sdk/appsdk#mcp-workflow-agents

Next: AppSDK → MCP on Workflow Agents to pass connectors and check metadata.tools_called.

Models

class DeployedAgent

DeployedAgentPydantic Model

Represents a deployed agent with all deployment metadata returned from the API.

PropertyTypeDescription
idstrUnique agent ID
namestrAgent name (slug format)
slugstrURL-friendly slug
versionstrSemantic version
display_namestr | NoneHuman-readable name
descriptionstr | NoneShort description
deployment_statusstrStatus: 'active', 'pending', 'error'
deployment_typestrType: 'config_based', 'adk', 'file'
endpoint_urlstr | NoneAgent invocation endpoint
cloud_providerstr | NoneCloud provider (e.g., 'gcp')
regionstr | NoneDeployment region
hipaa_compliantboolHIPAA compliance flag
hipaa_verifiedboolHIPAA verification status
created_atdatetime | NoneCreation timestamp
deployed_atdatetime | NoneDeployment timestamp

class DeploymentResult

DeploymentResultPydantic Model

Result of a deployment operation with success status and metadata.

successboolWhether deployment succeeded
agentDeployedAgent | NoneDeployed agent (if successful)
messagestrResult message
errorstr | NoneError message (if failed)
deployment_duration_secondsfloat | NoneTime taken to deploy

Complete Examples

Basic Agent Deployment

from hikigai.agentsdk import AgentClient, AgentConfig, InputSchema, OutputSchema, StringField

client = AgentClient()

agent = client.deploy(AgentConfig(
    name="customer-support",
    display_name="Customer Support Bot",
    description="Handles customer inquiries",
    instruction="You are a helpful customer support agent.",
    model="claude-3.5-sonnet",
    input_schema=InputSchema(fields={"message": StringField(required=True)}),
    output_schema=OutputSchema(fields={"response": StringField()}),
    timeout=60,
    memory_mb=512,
    version="1.0.0"
))

print(f"Deployed: {agent.endpoint_url}")

With Complex Schemas

from hikigai.agentsdk import ArrayField, ObjectField, IntegerField

config = AgentConfig(
    name="diagnosis-agent",
    display_name="Diagnosis Assistant",
    description="Provides diagnosis suggestions",
    instruction="Analyze symptoms and suggest diagnoses...",
    input_schema=InputSchema(
        fields={
            "symptoms": ArrayField(items=StringField()),
            "patient_age": IntegerField(minimum=0, maximum=150),
            "medical_history": ObjectField(properties={
                "conditions": ArrayField(),
                "medications": ArrayField()
            })
        }
    ),
    output_schema=OutputSchema(
        fields={
            "diagnoses": ArrayField(items=ObjectField(properties={
                "name": StringField(),
                "confidence": IntegerField(minimum=0, maximum=100),
                "icd10_code": StringField()
            })),
            "recommendations": ArrayField(items=StringField())
        }
    ),
    timeout=120,
    memory_mb=1024,
    version="1.0.0",
    hipaa_compliant=True
)

agent = client.deploy(config)

Managing Agents

# List all agents
agents = client.list_agents()
for agent in agents:
    print(f"{agent.name}: {agent.deployment_status}")

# Get specific agent
agent = client.get_agent("customer-support")
print(agent.version)
print(agent.endpoint_url)

# Delete agent
client.delete_agent("customer-support")

Deployment Methods

There are two ways to deploy agents on Hikigai: using SDK methods or calling the API directly. Choose based on your use case.

SDK Methods (.deploy)

The recommended approach for most use cases. Simple, validated, and handles all the complexity for you.

from hikigai.agentsdk import AgentClient, AgentConfig

client = AgentClient(api_key="your-api-key", project_id="your-project-id")
agent = client.deploy(AgentConfig(
    name="medical-coder",
    instruction="Extract ICD-10 codes...",
    model="claude-3.5-sonnet"
))
✓ Use SDK Method When:
  • • You're deploying from Python
  • • You want automatic validation and error handling
  • • You prefer a simple, one-liner deployment

Multi-Cloud Deployment

Whatever you set as the default under Organization settings → Cloud accounts is used when you deploy. Omit cloud_provider and cloud_credential_name to use that default. Pass cloud_provider="gcp" or "aws" only when you need to override it.

  • Set or change the default under Organization settings → Cloud accounts (“Set as default”).
  • Personal workspaces with no cloud account fall back to Hikigai's platform cloud.
  • Team orgs need a default cloud account (or an explicit override) before deploy.
# Uses Organization settings → Cloud accounts default
agent = client.deploy(config)

# Override provider when needed (set on AgentConfig)
config = AgentConfig(
    name="my-agent",
    instruction="...",
    version="1.0.0",
    cloud_provider="aws",  # or "gcp"
)
agent = client.deploy(config)

# Or pick a specific account by name
agent = client.deploy(
    config,
    cloud_credential_name="my-gcp-account",
)

Events & Webhooks

client.events covers webhook subscriptions and live event streaming for agent deploy/delete, jobs, invocations, and storage.

sub = client.events.create_webhook(
    url="https://ci.example.com/hooks/hikigai",
    event_types=["agent.deployed", "agent.deleted"],
)
print(sub.secret)  # shown once

Error Handling

DeploymentError / HikigaiError

Raised when deployment or API requests fail

from hikigai.agentsdk import HikigaiError, DeploymentError

try:
    agent = client.deploy(config)
except DeploymentError as e:
    print(f"Deployment failed: {e}")
except HikigaiError as e:
    print(f"API error: {e}")

ValidationError / ConfigurationError

Raised when configuration validation fails or credentials are missing

from hikigai.agentsdk import ValidationError, ConfigurationError

try:
    config = AgentConfig(name="invalid name!")  # Invalid chars
except ValidationError as e:
    print(f"Validation error: {e}")

AuthenticationError

Raised when the API key is invalid or missing

from hikigai.agentsdk import AuthenticationError

try:
    client = AgentClient(api_key="invalid-key", project_id="proj_123")
    agent = client.list_agents()
except AuthenticationError as e:
    print(f"Authentication failed: {e}")