Python SDK
Use the Python SDK when chat operations are part of an application workflow.
Create a client
from skyportalai import Skyportal
client = Skyportal(
api_key="YOUR_SKYPORTAL_API_KEY",
base_url="https://app.skyportal.ai",
timeout=30.0,
max_retries=2,
)
| Parameter | Default | Description |
|---|---|---|
api_key |
SKYPORTAL_API_KEY |
API credential; required |
base_url |
SKYPORTAL_BASE_URL or production |
API root (trailing slash removed) |
timeout |
30.0 |
Per-request timeout seconds; must be greater than zero |
max_retries |
2 |
Retry budget for idempotent GET requests; must be zero or greater |
session |
new requests.Session |
Optional caller-owned session |
Prefer a context manager:
close() only closes sessions created by the SDK. A caller-supplied session remains caller-owned.
Create and monitor a chat
from skyportalai import Skyportal
with Skyportal() as client:
chat = client.chat.create_chat(
"Report disk usage and identify the largest directory",
server_id=42,
)
status = chat.wait(timeout=300)
print(chat.chat_id, status.status)
for message in chat.messages().messages:
print(f"{message.role}: {message.content}")
wait() polls while status is processing or uninitialized. It returns on settled state or approval request, and raises WaitTimeoutError on timeout.
Manual approval flow
from skyportalai import Skyportal
with Skyportal() as client:
chat = client.chat.create_chat("Check disk usage", server_id=42)
status = chat.wait()
if status.status == "awaiting_approval":
for approval in status.pending_approvals:
print("Requested type:", approval.type)
print("Requested command:", approval.command)
# Approve only after authorized human review.
chat.approve(
approval.approval_id,
approval_type=approval.type or "bash_command",
command=approval.command or None,
)
status = chat.wait()
Reject flow:
chat.reject(
approval.approval_id,
approval_type=approval.type or "bash_command",
reason="Outside the approved scope",
)
Optional approval callback:
def approval_policy(approval):
print(approval.command)
return None # Keep pending for separate human decision.
status = chat.wait(on_approval=approval_policy)
Continue, switch, or cancel
chat.send("Now inspect the previous job logs")
chat.select_server(84)
chat.cancel(reason="No longer required")
Read-only observability
execution = chat.execution_status()
events = chat.events(after_timestamp=None, event_types=["tool_call"], limit=100)
tool_calls = chat.tool_calls(limit=100)
reasoning = chat.reasoning(limit=100)
plans = chat.plans()
evaluations = chat.evaluations(evaluator_type=None)
environment = chat.environment()
These methods currently return dictionaries from server payloads. Preserve unknown fields.
Resource-level methods
status = client.chat.get_status(chat_id)
messages = client.chat.get_messages(chat_id, after_sequence=0, limit=100)
client.chat.send_message(chat_id, "Continue")
client.chat.select_server(chat_id, server_id)
client.chat.approve(chat_id, approval_id, approval_type="bash_command", command=command)
client.chat.reject(chat_id, approval_id, approval_type="bash_command", reason=reason)
client.chat.cancel(chat_id, reason="No longer required")
Returned types
Primary models are immutable dataclasses and include raw for forward compatibility.
| Type | Important fields |
|---|---|
User |
name, raw |
Chat |
chat_id, raw |
ChatStatus |
status, workflow_type, pending_approvals, raw |
PendingApproval |
approval_id, type, command, plan_id, reason, raw |
ApprovalResult |
success, decision, raw |
Message |
role, content, sequence, raw |
MessagesPage |
messages, has_more, raw |
Message block payloads are flattened into plain text in Message.content; untouched server values remain in Message.raw.