Skip to main content

Python SDK for SeaArt agent-gateway APIs

Project description

Sea Agent Python SDK

Beta: SDK APIs and agent-gateway behavior may still change with gateway versions.

Python SDK for the SeaArt agent-gateway. It wraps gateway APIs for catalog lookup, tool registration, skill registration, agent registration, hook management, chat completion, SSE streaming, WebSocket streaming, chat replay, and chat cancellation.

Features:

  • Standard-library runtime by default, with no required third-party runtime dependencies
  • Automatic /agent-v2 API prefix normalization for agent-gateway
  • Explicit client configuration with endpoint, API key, and request headers
  • OpenAI-style multi-turn messages and multimodal content parts
  • SSE stream parsing by default, with WebSocket support as an optional dependency
  • Automatic stream resume with event-sequence deduplication and configurable backoff
  • Pythonic snake_case APIs, with a small set of Go SDK-style aliases for migration

Available Resources

Resource Client field What it does
System client.system / client.System Health and metrics checks
Catalog client.catalog / client.Catalog List resolved catalog entries
Tools client.tools / client.Tools Register, list, update, delete, and resolve tools
Skills client.skills / client.Skills Register, list, update, and delete skills
Agents client.agents / client.Agents Register, list, update, delete, and inspect agents
Hooks client.hooks / client.Hooks Manage the multimodal charge reservation hook
Chat client.chat / client.Chat Run chat, stream chat, replay events, and cancel chats

Installation

Install from PyPI:

pip install --upgrade sea-agent-sdk

Install WebSocket streaming support when needed:

pip install --upgrade 'sea-agent-sdk[ws]'

Install PyYAML support when you need fuller YAML config handling:

pip install --upgrade 'sea-agent-sdk[yaml]'

Install the latest code from GitHub:

pip install --upgrade git+https://github.com/SeaArt-Infra/sea-agent-sdk-py.git

Requires Python 3.10 or newer.

Configuration

Create a client with explicit options:

import os

import sea_agent_sdk as sa

client = sa.Client(
    sa.ClientOptions(
        endpoint="http://127.0.0.1:8080",
        api_key=os.environ.get("AGENT_GATEWAY_API_KEY", ""),
        headers={"X-User-ID": "production-line-123"},
    )
)

endpoint may be the gateway base URL or a URL that already includes /agent-v2. The SDK appends /agent-v2 before sending requests when it is missing.

Pass X-User-ID in ClientOptions.headers when tools, skills, or agents write operations need provider, owner, or operator metadata.

System Checks

health = client.system.health()
metrics = client.system.metrics()
print(health)

Listing Resources

List APIs pass gateway filters through SDK option objects. Common filters are search, status, provider, public, limit, and offset. Compatibility filters include source_kind, owner_id, and category.

tools = client.tools.list(
    sa.ToolListOptions(
        provider="web-tools-mcp",
        status="active",
        limit=20,
    )
)
print(tools)

You can also pass a plain dictionary:

tools = client.tools.list(
    {
        "provider": "web-tools-mcp",
        "status": "active",
        "limit": 20,
    }
)

Pagination follows the gateway behavior: limit defaults to 20 when omitted or <= 0, the gateway caps values above 200, and offset starts at 0.

Chat Requests

Use message for the common single-user-message case:

result = client.chat.run(
    sa.ChatRunOptions(
        agent_id="33333333-3333-4333-8333-333333333333",
        message="Fetch https://example.com and explain what it is.",
    )
)
print(result)

Use skill_ids to temporarily mount extra Skills for a registered Agent run when it needs one-off capabilities without changing its saved configuration. Agent Gateway accepts at most 20 active, visible Skill UUIDs, merges them after the Agent's own Skills, dedupes repeated IDs, rejects skill_ids when agent_config is used, and only lets Skill runtime config fill Agent defaults that are unset.

result = client.chat.run(
    sa.ChatRunOptions(
        agent_id="33333333-3333-4333-8333-333333333333",
        skill_ids=["11111111-1111-1111-1111-111111111111"],
        message="Use the extra skill for this run.",
    )
)

Use messages for multi-turn conversations:

result = client.chat.run(
    sa.ChatRunOptions(
        agent_id="33333333-3333-4333-8333-333333333333",
        messages=[
            sa.ChatMessage(role="system", content="Answer in concise Chinese."),
            sa.ChatMessage(role="user", content="Fetch https://example.com and explain what it is."),
        ],
    )
)

Use OpenAI-style content parts for multimodal messages:

result = client.chat.run(
    sa.ChatRunOptions(
        agent_id="33333333-3333-4333-8333-333333333333",
        messages=[
            sa.ChatMessage(
                role="user",
                content=[
                    sa.text_chat_content("Describe this image."),
                    sa.image_url_chat_content("https://example.com/image.png"),
                ],
            )
        ],
    )
)

Attach request metadata and per-request headers when gateway or worker tracing needs them:

result = client.chat.run(
    sa.ChatRunOptions(
        request_id="req_123",
        agent_id="33333333-3333-4333-8333-333333333333",
        category="fabric",
        message="Summarize this request context.",
        metadata={
            "session_id": "sess_123",
            "user_id": "user_456",
            "trace_id": "trace_789",
        },
        headers={"X-Trace-ID": "trace_789"},
    )
)

request_id, category, and metadata are sent in the chat body. Custom headers are forwarded when the SDK creates non-streaming, SSE, or WebSocket chat requests. Use extra_body for gateway fields that are not yet exposed as first-class SDK options.

SSE Streaming

SSE is the default stream transport and works well with most HTTP gateways and proxies:

text = client.chat.run_stream(
    sa.ChatRunOptions(
        agent_id="33333333-3333-4333-8333-333333333333",
        message="Fetch https://example.com and summarize it in one paragraph.",
    ),
    sa.ChatStreamHandlers(
        on_text_delta=lambda delta, event: print(delta, end=""),
        on_event=lambda event: None,
    ),
)

print("\n\nFinal text:", text)

run_stream(), stream_completion(), and stream() automatically resume transiently disconnected streams. For a newly created run, the SDK keeps a stable request_id, captures the run_id from chat.created, and reconnects with the last delivered event sequence. Events already delivered before the disconnect are not emitted again.

Auto-resume makes up to three reconnect attempts by default. Configure or disable it through the stream handlers:

handlers = sa.ChatStreamHandlers(
    max_reconnects=5,
    reconnect_delay=0.25,
    max_reconnect_delay=5.0,
    on_reconnect=lambda info: print(
        f"resuming {info.run_id} after seq {info.after_seq} (attempt {info.attempt})"
    ),
)

# Use auto_resume=False when the caller owns reconnection.
Handler field Default Behavior
auto_resume True Resume a stream that closes before a terminal event
max_reconnects 3 Reconnect attempts after the initial connection; 0 disables retries
reconnect_delay 0.25 Initial reconnect delay in seconds
max_reconnect_delay 5.0 Maximum exponential-backoff delay in seconds
on_reconnect None Receives ChatReconnectInfo(attempt, run_id, after_seq, delay, error)

EOF, network failures, HTTP 408/429, and 5xx responses are retried. Other 4xx responses (including WebSocket handshake failures), WebSocket error messages, missing WebSocket dependencies, invalid UTF-8, and exceptions raised by on_event, on_text_delta, or on_reconnect are raised immediately. The complete terminal set is response.completed, response.failed, response.canceled, response.cancelled, chat.response, chat.completed, chat.failed, and chat.cancelled. The SDK closes the transport as soon as a terminal event is delivered, ignores later events in the same chunk, and does not surface a connection error reported while closing. Incomplete SSE frames at EOF are discarded and replayed from the last complete seq when reconnection is enabled.

Automatic resume covers connection loss while the current process is running. Persist run_id and event.seq in the application when a stream must survive a process restart.

WebSocket Streaming

WebSocket streaming is optional. Install the ws extra first:

pip install --upgrade 'sea-agent-sdk[ws]'
text = client.chat.run_stream(
    sa.ChatRunOptions(
        agent_id="33333333-3333-4333-8333-333333333333",
        message="Tell me what tools you can use, then answer with a short plan.",
    ),
    sa.ChatStreamHandlers(
        transport=sa.STREAM_TRANSPORT_WS,
        on_text_delta=lambda delta, event: print(delta, end=""),
    ),
)

Worker Stream Event Format

agent-gateway forwards worker stream events as SSE blocks or WebSocket messages. The SDK normalizes both transports into ChatStreamEvent(event, data, id, seq). id preserves the wire event ID and seq is its numeric form, or 0 when an event such as a heartbeat has no sequence. Use on_text_delta for assistant text and on_event for all raw lifecycle, tool, skill, and terminal events.

SSE frames use the standard event/data envelope:

event: response.text.delta
data: {"type":"response.text.delta","response_id":"run_xxx","item_id":"item_run_xxx_msg","output_index":0,"content_index":0,"delta":"hello"}
id: 42

WebSocket frames carry the same payload under data:

{
  "id": "42",
  "event": "response.text.delta",
  "data": {
    "type": "response.text.delta",
    "response_id": "run_xxx",
    "item_id": "item_run_xxx_msg",
    "output_index": 0,
    "content_index": 0,
    "delta": "hello"
  }
}

Common worker event sequence:

Event When it appears Important fields in data
response.created Run accepted and response object created type, response.id, response.status, response.model, response.metadata
response.in_progress Run enters processing type, response.id, response.status
response.output_item.added Assistant message item or tool call item starts response_id, output_index, item.type, item.id, item.status; tool calls also include item.call_id, item.name
response.content_part.added Assistant text content part starts response_id, item_id, output_index, content_index, part.type
chat.delta Legacy assistant text chunk content, text, or delta
response.text.delta Assistant text token/chunk response_id, item_id, output_index, content_index, delta
response.function_call_arguments.done Tool call arguments are finalized response_id, item_id, call_id, name, arguments as a JSON string
fabric.tool.started Worker starts a tool call tool.id, tool.call_id, tool.name, tool.status, tool.arguments
fabric.tool.completed Worker finishes a tool call tool.status, tool.output, tool.output_text, tool.output_type; structured tool protocols may add tool.structured_content, tool.protocol_type, tool.tool_response
fabric.skill.started Worker loads a skill through a read_file tool call skill.id, skill.name, skill.status, skill.path
fabric.skill.completed Skill file load completes skill.status, skill.output, skill.output_text, skill.path
response.text.done Assistant final text is known response_id, item_id, content_index, text
response.content_part.done Assistant text content part completes part.type, part.text
response.output_item.done Assistant message or function call output item completes item.type, item.status, item.content for messages; item.call_id, item.arguments, item.output for tool calls
response.completed Run completed successfully response.id, response.status, response.usage, response.elapsed_ms, response.metadata, response.output
response.failed Run failed response.status, response.error.type, response.error.code, response.error.message
response.canceled / response.cancelled Run was canceled response.status, response.cancel_reason

The SDK accumulates returned text from response.text.delta. It also keeps compatibility with legacy response.output_text.delta, chat.delta, chat.response, and message.delta text events. Tool, skill, usage, metadata, and terminal details are not passed to on_text_delta; inspect them in on_event.

Replay an Existing Chat

If another SDK client or application created the chat, subscribe by chat ID. after_seq selects the initial cursor; subsequent transient disconnects are resumed automatically from the latest delivered event.seq.

text = client.chat.stream(
    "chat_xxxxxxxxxxxxx",
    sa.ChatStreamHandlers(
        on_text_delta=lambda delta, event: print(delta, end=""),
    ),
    sa.ChatEventsOptions(after_seq=0),
)

Use sa.STREAM_TRANSPORT_WS with the same API to replay over WebSocket.

Inline Agent Config

Pass agent_config when the request should not reference a registered agent. Runtime fields such as temperature, max_turns, and timeout are forwarded by agent-gateway to the worker.

result = client.chat.run(
    sa.ChatRunOptions(
        category="fabric",
        agent_config={
            "agent": {
                "name": "inline-assistant",
                "model": "gpt-4.1-mini",
                "reasoning_effort": "medium",
                "temperature": 0.2,
                "max_turns": 6,
                "timeout": 120,
                "system_prompt": "Answer in Chinese and keep the answer brief.",
            }
        },
        message="Explain what agent-gateway does.",
    )
)

Declare a sandbox template when the gateway should start a sandbox for the inline agent. Supported template values are react-game and react-web.

result = client.chat.run(
    sa.ChatRunOptions(
        category="fabric",
        agent_config={
            "agent": {
                "name": "inline-sandbox-agent",
                "model": "gpt-4.1-mini",
                "system_prompt": "Build and modify React apps inside the sandbox.",
            },
            "runtime": {
                "sandbox": {
                    "sandbox_template": "react-game",
                }
            },
        },
        message="Create a small React game.",
    )
)

Register Tools, Skills, and Agents

agent-gateway uses server-generated UUID id values as resource identities. Registry lookup and association should use UUIDs; do not send removed tool_key, skill_key, or agent_key fields.

Register an HTTP Tool

tool = client.tools.register(
    {
        "name": "search_web",
        "description": "Search public web pages.",
        "runtime_type": "http",
        "endpoint": "https://example.com/tools/search",
        "service_name": "example",
        "method": "POST",
        "parameters": {
            "type": "object",
            "properties": {"query": {"type": "string"}},
            "required": ["query"],
        },
        "enabled": True,
        "public": False,
    }
)

service_name is a top-level tool field beside name. It identifies the backing service shared by tools on the same server. If omitted, the gateway derives it from the endpoint host prefix; builtin and no-endpoint tools default to deepagent. Do not put service_name in metadata/config, and do not send inject_user_credentials in user-facing registration payloads.

Register a Skill

skill = client.skills.register(
    {
        "name": "web-research",
        "description": "Research a topic with web tools.",
        "instruction": "Search, compare sources, and summarize findings.",
        "required_tools": ["22222222-2222-4222-8222-222222222222"],
        "enabled": True,
        "public": False,
    }
)

When required_tools or optional_tools contains registered HTTP Tool UUID strings, the gateway normalizes them to:

{"type": "http", "ref": "<tool-uuid>"}

Use object entries when you need non-default tool types:

{
    "required_tools": [
        {"type": "http", "ref": "22222222-2222-4222-8222-222222222222"},
        {"type": "builtin", "ref": "seaart:generate_image"},
        {"type": "mcp", "ref": "filesystem:read_file", "server": "mcp-filesystem"},
    ]
}

type is required and must be http, http_batch, builtin, or mcp. MCP entries also require server. Do not use Tool name or old tool_key values as ref.

Register an Agent

agent = client.agents.register(
    {
        "name": "web_assistant",
        "category": "fabric",
        "system_prompt": "You are a web research assistant.",
        "skills": ["11111111-1111-4111-8111-111111111111"],
        "config": {"temperature": 0.2, "max_turns": 6},
        "enabled": True,
    }
)

Skill Runtime Rules

Field Rule
name Must match ^[a-z0-9-]+$; use lowercase letters, numbers, and hyphens only
description Required; keep it short because the gateway writes it to inline SKILL.md frontmatter
instruction Required; full Markdown body for the skill
required_tools / optional_tools Use UUID refs for registered HTTP, HTTP Batch, and registered builtin tools

When an agent runs with a registered skill, the gateway assembles an inline skill document:

---
name: web-research
description: Research a topic with web tools.
---

Search, compare sources, and summarize findings.

Hook Endpoints

Register the single hook endpoint owned by the configured API key:

from sea_agent_sdk import HookRequest

request = HookRequest(
    name="production-line-hook",
    endpoint="https://example.com/agent-hook",
    description="Receives multimodal charge reservation events for the configured API key.",
)
hook = client.hooks.register(request)
updated = client.hooks.update(request)
deleted = client.hooks.delete()

Hook management requests use ClientOptions.api_key as Authorization: Bearer ...; registration and update request fields are name, endpoint, and description. One API key owns at most one active Hook. Registration creates a Hook and returns 409 Conflict when one is already active; after deletion, the same API key can register again.

Callback event: multimodal.charge.reserve

The Worker sends this event with fixed POST immediately before submitting a multimodal model operation. Callback metadata is copied from the individual chat request:

{
  "event_id": "evt_...",
  "event": "multimodal.charge.reserve",
  "run_id": "run_...",
  "metadata": {},
  "data": {
    "operation_id": "op_...",
    "tool_name": "generate",
    "model": "model-name",
    "modality": "multimodal",
    "cost": "0.035",
    "currency": "USD"
  }
}

For this event, the endpoint must synchronously return an HTTP success status and a top-level JSON object. Approval returns {"approved":true}. Rejection returns {"approved":false} and can include code and message, for example {"approved":false,"code":"insufficient_balance","message":"Balance is insufficient"}.

API Reference

Area Methods
System health(), metrics()
Catalog list(options)
Tools register(payload), list(options), get(tool_id), update(tool_id, payload), delete(tool_id), resolve(tool_id)
Skills register(payload), list(options), get(skill_id), update(skill_id, payload), delete(skill_id)
Agents register(payload), list(options), get(agent_id), update(agent_id, payload), delete(agent_id), capabilities(agent_id)
Hooks register(payload), update(payload), delete()
Chat create_completion(payload), stream_completion(payload, handlers), run(options), run_stream(options, handlers), get(chat_id), events(chat_id, options), stream(chat_id, handlers, options), cancel(chat_id)

Stream Utilities

If you need to process raw stream data yourself, the package also exports these helpers:

from sea_agent_sdk import (
    ChatStreamProcessor,
    parse_sse,
    parse_websocket_event,
    text_from_stream_event,
)

Local Development

make test
make build
make check

Next Steps

  • Start with client.chat.run() for non-streaming requests.
  • Use client.chat.run_stream() with SSE for most streaming integrations.
  • Use client.chat.stream() with after_seq to subscribe to an existing chat or resume after a process restart; active-process disconnects are handled automatically.
  • Register tools, skills, and agents with UUID-based references only.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sea_agent_sdk-0.2.1.tar.gz (32.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sea_agent_sdk-0.2.1-py3-none-any.whl (22.3 kB view details)

Uploaded Python 3

File details

Details for the file sea_agent_sdk-0.2.1.tar.gz.

File metadata

  • Download URL: sea_agent_sdk-0.2.1.tar.gz
  • Upload date:
  • Size: 32.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for sea_agent_sdk-0.2.1.tar.gz
Algorithm Hash digest
SHA256 64d12fb2645248a7e4ff68d2f2c3bf711069c1a9b92f1af762948ab0f9ef85ce
MD5 057e798f0e4ebdd86fa8080045e44dc2
BLAKE2b-256 a7bd64ae62481cc36f247b365ef148e47a086ade47e1abd9b5f882c3040c659f

See more details on using hashes here.

File details

Details for the file sea_agent_sdk-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: sea_agent_sdk-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 22.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for sea_agent_sdk-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 580ada60068804a3114b51e64d7092ce58b39d034503a7691de1e2e4e7dffd6e
MD5 81f97bf48e288eb33c024e1e29529900
BLAKE2b-256 03731522250e913429436d35c7d897334727668b7204a4008f72122b9b9569d6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page