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.
Installation
Using pip
pip install hikigai-agentsdkQuick 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
AgentClientCoreMain 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
| Method | Returns | Description |
|---|---|---|
deploy(config, timeout=1200.0, poll_interval=10.0) | DeployedAgent | Deploy a new agent and poll until active |
list_agents() | List[DeployedAgent] | List all deployed agents |
get_agent(agent_id: str) | DeployedAgent | Get agent by ID or slug |
update_agent(agent_id: str, update: Dict) | DeployedAgent | Update agent metadata/config and trigger redeploy |
delete_agent(agent_id: str) | None | Delete 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() | JobsClient | Background job queue (enqueue, wait, stream, cancel, replay) |
storage() | StorageClient | App object storage (upload, signed_url, list, get, delete) |
Context Manager
with AgentClient() as client:
agent = client.deploy(config)
# Resources automatically releasedclass JobsClient (client.jobs)
client.jobsJobsBackground job queue for long-running agent work. Access via AgentClient.jobs.
| Method | Returns | Description |
|---|---|---|
enqueue(job_type, payload, agent_id=None, priority='standard', ...) | EnqueuedJob | Enqueue a background job |
get(job_id: str) | JobDetail | Fetch 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) | JobDetail | Cancel a queued or running job |
replay(job_id, override_retry_policy=None, override_payload=None) | EnqueuedJob | Re-enqueue a failed job |
wait(job_id, timeout=600.0, poll_interval=5.0) | JobDetail | Block 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.storageStoragePlatform-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
| Method | Returns | Description |
|---|---|---|
upload(app_id, file, filename, content_type='application/octet-stream', metadata=None, ttl=None) | StorageUploadResult | Multipart 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) | SignedUrlResult | Mint a temporary download URL (signed_url, expires_in, expires_at) |
list(app_id, content_type=None, status='active', limit=20, page=1) | StorageListResult | Paginated list; filter by content_type and status |
get(app_id, object_id) | StorageObjectInfo | Fetch metadata for one object (filename, size, status, metadata, …) |
delete(app_id, object_id) | None | Delete an object |
Return shapes
StorageUploadResult | dataclass | object_id, object_key, original_filename, content_type, size_bytes, signed_url, expires_at, created_at |
SignedUrlResult | dataclass | object_id, signed_url, expires_in, expires_at |
StorageObjectInfo | dataclass | object_id, original_filename, content_type, size_bytes, metadata, status, upload_source, expires_at, created_at |
StorageListResult | dataclass | objects, 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
RoomSessionRealtimeCreate 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",
)| Param | Type | Description |
|---|---|---|
base_url* | str | Platform base URL (same as AgentClient); RoomSession opens the rooms WebSocket from this |
api_key | str | None | Project API key — full subscribe/publish/manage/rtc for that project |
access_token | str | None | Short-lived JWT (e.g. from AgentClient.get_auth_token()) |
room_token | str | None | End-user room token with scoped rooms + capabilities |
project_id | str | None | Required 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_id | str | None | Server-assigned connection id after auth |
capabilities | List[str] | Granted caps after ready (subscribe, publish, manage, rtc) |
last_seq | Dict[str, int] | Per-room last delivered message seq (used on reconnect) |
Methods
| Method | Returns | Description |
|---|---|---|
connect() | None | Open WS, send auth, wait for ready |
close() | None | Send disconnect and close the socket |
reconnect() | None | Reopen + rejoin all rooms with last_seq; re-announce RTC peers |
join(room, last_seq=None) | Dict | Create (if new) or join a room; optional seq for replay |
leave(room) | None | Leave room (also drops RTC peer if any) |
publish(room, event, data=None, *, echo=False) | None | Broadcast an event; echo=True also delivers to sender |
who(room) | None | Request member list; reply arrives on the iterator |
ping() | None | Keepalive ping |
refresh(room_token) | None | Rotate room_token in-place without reconnecting |
rtc_join(room, *, mode=None, agent_id=None, metadata=None) | Dict | Announce as WebRTC peer (requires rtc capability + prior join) |
rtc_leave(room) | None | Leave RTC session but stay a room member |
rtc_offer(room, target, sdp) | None | Send SDP offer to one peer |
rtc_answer(room, target, sdp) | None | Answer one peer's offer |
rtc_candidate(room, target, candidate) | None | Trickle ICE candidate (RTCIceCandidateInit shape) |
rtc_who(room) | None | Request current RTC peer list |
Inbound frames (async for frame in room)
| type | Meaning |
|---|---|
joined | Join ack + your capabilities + members |
message | Published event (room, event, data, seq, ts) |
presence | Members joined/left |
error | Normative code (unauthorized, forbidden, room_full, cursor_expired, …) |
rtc_joined / rtc_peer_joined / rtc_peer_left | RTC peer lifecycle + ice_servers |
rtc_offer / rtc_answer / rtc_candidate | Directed SDP/ICE signalling (media is peer-to-peer) |
Reconnect & delivery
- Default delivery is at-most-once. The client tracks
last_seqper room and dedupes replays. reconnect()rejoins withlast_seqso 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 ModelComprehensive configuration for deploying an agent. Supports schemas, tools, versioning, and HIPAA compliance.
| Property | Type | Description |
|---|---|---|
| Identity | ||
name* | str | Unique agent name (3-64 chars, lowercase, hyphens) |
display_name* | str | Human-readable display name (3-100 chars) |
description* | str | Short description (10-500 chars) |
long_description | str | None | Full documentation (max 5000 chars) |
| Core | ||
agent_type | str | Orchestration: llm (single), sequential, parallel, or loop — see Workflow Agents Default: llm |
instruction* | str | System prompt/instruction (10-50,000 chars) |
model | str | LLM model to use Default: claude-3.5-sonnet |
| Multi-Agent Support | ||
sub_agents | List[SubAgentConfig] | Nested leaves for sequential/parallel/loop roots Default: [] |
| Advanced Features | ||
planner_config | PlannerConfig | None | Enable planning/reasoning capabilities |
code_execution | bool | Enable code execution capability Default: False |
generation_config | GenerationConfig | None | LLM generation parameters |
| State Management | ||
output_key | str | None | Key to save agent output in state for downstream agents |
include_contents | str | None | Control conversation history inclusion |
max_iterations | int | None | Maximum iterations for LoopAgent |
| Classification | ||
category | str | Category from predefined list Default: documentation |
tags | List[str] | Tags for discovery (max 10) Default: [] |
| Schemas | ||
input_schema* | InputSchema | Dict | Input data structure definition |
output_schema* | OutputSchema | Dict | Output data structure definition |
| Modality | ||
input_modality | str | Input modality: text, audio, image, video, document, or combinations Default: text |
output_modality | str | Output modality: text, audio, image, document, or combinations Default: text |
vad | VadConfig | None | Live automatic VAD (applied only when input_modality includes audio). Defaults: silence 800ms, sensitivities low/low |
| Tools & Connectors | ||
tools | List[Any] | Tools available to the agent Default: [] |
connectors | List[ConnectorConfig] | Root MCP connectors — attached at invoke/live to every LlmAgent leaf (Sequential/Parallel/Loop), not only a simple LLM root Default: [] |
| Runtime | ||
timeout | int | Request timeout in seconds (5-300) Default: 60 |
memory_mb | int | Memory allocation in MB (128-4096) Default: 512 |
min_instances | int | Minimum scaling instances (0-10) Default: 0 |
max_instances | int | Maximum scaling instances (1-100) Default: 10 |
| Versioning | ||
version* | str | Semantic version (e.g., '1.0.0') |
changelog | str | None | What changed in this version |
| Compliance & Visibility | ||
hipaa_compliant | bool | Agent handles PHI per HIPAA Default: True |
public | bool | Publicly listed in marketplace Default: False |
| Cloud Deployment | ||
cloud_provider | str | None | Allowed values: 'gcp' or 'aws'. Omit to use the org/project default cloud account (Organization settings → Cloud accounts, or a project override). |
cloud_credential_name | str | None | Optional Cloud accounts name. Omit to use the org/project default account. |
gcp_region | str | GCP region for deployment Default: us-central1 |
aws_region | str | AWS region for deployment Default: us-east-1 |
| Healthcare Spec | ||
risk_tier | str | None | Healthcare risk tier Default: low |
clinical_domain | str | None | Clinical domain category |
a2a_skills | List[Dict] | Machine-readable capabilities for AI-to-AI discovery Default: [] |
resource_limits | Dict[str, str] | Container resource limits Default: {'cpu': '1', 'memory': '512Mi'} |
fhir_resources | List[Dict] | Required FHIR resources for agent operation Default: [] |
prompt_version | str | None | Specific version of the clinical prompt Default: 1.0.0 |
requires_physician_oversight | bool | Does this agent require human physician sign-off? Default: False |
fda_clearance_status | str | FDA 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 ModelAutomatic voice activity detection for live audio agents (Gemini Live realtime_input_config). Applied only when input_modality includes audio.
| Property | Type | Description |
|---|---|---|
silence_duration_ms | int | None | Silence in ms before the user turn is committed (200–2000) Default: 800 |
end_of_speech_sensitivity | str | None | 'high' commits sooner after a pause; 'low' waits longer Default: low |
start_of_speech_sensitivity | str | 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 ModelDefine 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().
| Type | Behavior | Live notes |
|---|---|---|
sequential | Leaves run one after another | Shared mic; advance via task_completed or after_output |
parallel | Leaves run concurrently | Mic teed to all branches; prefer text-only outs to avoid audio clash |
loop | Repeats leaf sequence until escalate / max_iterations | Same leaf handoff rules as sequential |
class SubAgentConfig
SubAgentConfigPydantic ModelOne 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* | str | Leaf name (letters, numbers, hyphens, underscores). For marketplace reuse, use the marketplace agent name/slug. |
agent_type | str | llm (default) or nested sequential/parallel/loop. Not required for marketplace reuse. Default: llm |
model | str | None | Model for this leaf. Required for your own agents; omitted when source='marketplace' (loaded from the source agent). |
instruction | str | None | Leaf system prompt. Required for your own agents (min 10 chars). Omit when source='marketplace' — the platform hydrates it. |
description | str | None | Short description (own agents). Optional display metadata for marketplace reuse. |
source | Literal["marketplace"] | None | Set 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_id | str | None | Optional explicit agent UUID to reuse (project-owned or marketplace-linked). Alternative to source='marketplace' + name. |
input_schema | dict | None | Optional leaf input schema (own agents). Hydrated automatically for marketplace reuse. |
output_schema | dict | None | Optional leaf output schema (own agents). Hydrated automatically for marketplace reuse. |
input_modality | str | text, audio, or combinations Default: text |
output_modality | str | text, audio, or combinations Default: text |
live_handoff | Literal["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 |
tools | List[str] | Tool names for this leaf Default: [] |
sub_agents | List[SubAgentConfig] | Nested children when agent_type is a workflow Default: [] |
max_iterations | int | None | LoopAgent 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-agentsNext: AppSDK → MCP on Workflow Agents to pass connectors and check metadata.tools_called.
Models
class DeployedAgent
DeployedAgentPydantic ModelRepresents a deployed agent with all deployment metadata returned from the API.
| Property | Type | Description |
|---|---|---|
id | str | Unique agent ID |
name | str | Agent name (slug format) |
slug | str | URL-friendly slug |
version | str | Semantic version |
display_name | str | None | Human-readable name |
description | str | None | Short description |
deployment_status | str | Status: 'active', 'pending', 'error' |
deployment_type | str | Type: 'config_based', 'adk', 'file' |
endpoint_url | str | None | Agent invocation endpoint |
cloud_provider | str | None | Cloud provider (e.g., 'gcp') |
region | str | None | Deployment region |
hipaa_compliant | bool | HIPAA compliance flag |
hipaa_verified | bool | HIPAA verification status |
created_at | datetime | None | Creation timestamp |
deployed_at | datetime | None | Deployment timestamp |
class DeploymentResult
DeploymentResultPydantic ModelResult of a deployment operation with success status and metadata.
success | bool | Whether deployment succeeded |
agent | DeployedAgent | None | Deployed agent (if successful) |
message | str | Result message |
error | str | None | Error message (if failed) |
deployment_duration_seconds | float | None | Time 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 onceError 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}")