Skip to content

blockether.vis.engine

Synchronous agent, session, execution-layer and Council APIs.

For installation, workflows and lifecycle choices, use the Python SDK guide.

class Agent:

Run one conversation, with optional application-owned tools.

Choose this entry point for sequential requests that should share history. Use send to get a blockether.vis.engine.Turn immediately, or run to wait for its result. Access session for transcripts, attachments and progress.

Arguments:
  • project: Project directory. Local execution resolves an existing directory immediately; gateway execution requires an absolute path on the gateway.
  • execution_layer: A blockether.vis.engine.LocalEngine or blockether.vis.engine.GatewayClient to borrow. When omitted, the agent creates and owns a local engine. Configure executable, credentials and transport timeouts on an explicit layer.
  • extensions: Iterable of blockether.vis.extension.Extension declarations. Their Python callables stay in your application and execute on the calling thread while you read, wait or iterate events.

Construction does not start a process or connect. Session access, context entry, send or run starts the conversation. Closing the default agent stops its private process and discards its temporary session database, not file edits. An explicitly supplied layer is borrowed: you must close it yourself, after all agents using it have finished. An agent cannot be reused after close.

Raises:
  • TypeError: The supplied layer does not implement blockether.vis.engine.ExecutionLayer, or an extension is unsupported.
  • ValueError: A project or extension declaration is invalid.
  • FileNotFoundError: The local project does not exist.
  • NotADirectoryError: The local project is not a directory.
Agent( project='.', *, execution_layer: ExecutionLayer | None = None, extensions=())
execution_layer
project
session: Session

The same conversation for all requests; connects on first access.

def register_extension(self, extension):

Add an application-owned Extension before this Agent's first request.

Callables keep their Python objects and execute on the SDK calling thread while you read, wait or iterate events. No code or closures are uploaded. Host-only extension fields are refused before connecting.

def send(self, request: str, **options) -> Turn:

Submit a request without waiting for the model to finish.

Arguments:
  • request: User message or an explicit slash command.
  • **options: Forwarded to blockether.vis.engine.Session.send, including provider, model, attachments and idempotency_key.
Returns:

A blockether.vis.engine.Turn bound to this conversation. Call its read, wait or cancel method to track or control this request. Further calls reuse the same conversation and its history.

Submission can make network calls and raise transport or gateway errors. No mutation is automatically retried. If you retry an uncertain submission, reuse an explicit idempotency key rather than accidentally starting it twice.

def run(self, request: str, *, timeout=300, **options):

Submit a request and return its final or suspended turn record.

Arguments:
  • request: User message or slash command, as for send.
  • timeout: Positive finite wait deadline in seconds; defaults to 300. This is separate from the layer's transport timeout.
  • **options: Submission options forwarded to send.
Returns:

The canonical turn dictionary, not a string. Inspect status: completed, failed, cancelled, suspended and error all end the wait. Failed model work is returned as a record, not raised as an exception by this method.

Raises:

Transport and gateway errors also propagate. Closing this agent stops unfinished work only when it owns the default local engine.

def close(self):

Detach callbacks and release only resources owned by this agent.

Repeated calls are safe. The default local engine is stopped and its temporary session database removed; project file edits remain. A borrowed execution layer and other agents using it remain open. Requests through this agent after closing raise blockether.vis.engine.TransportError.

@dataclass(frozen=True, slots=True)
class Council:

Communicate with other Vis sessions.

Obtain this handle with Session.council, rather than constructing it with internal binding fields. The handle captures its session's group and current activation when acquired; it is not a live alias for whichever run is latest.

Use members to discover active peers, publish to send a message and get to inspect replies. Publication, delivery and a completed answer are separate states. threads and read return cursor-based pages of conversation history.

Communication requires an available Council group. A disabled or missing group is reported when a communication operation or group_id needs it.

Council( _session: Any, _group_id: str, _activation_id: str | None, _binding_error: Exception | None = None)
group_id: str

Return the captured group or report why communication is unavailable.

def members(self) -> tuple[CouncilMember, ...]:

Active session ids, titles and states. This list is only a snapshot.

def publish( self, content: str, *, kind: Literal['complain', 'coordination', 'informational'], thread_id: int | None = None, title: str | None = None, ping: list[str] | str | None = None, idempotency_key: str | None = None, reply_required: bool = False, reply_to: int | None = None) -> CouncilEntry:

Publish a message, optionally requesting replies from selected sessions.

Arguments:
  • content: Message text. Keep secrets and private data out of messages.
  • kind: coordination for work and questions, informational for findings, or complain for failures and concrete improvements. Complaints enter the persistent improve register, not an external issue tracker. Include sanitized evidence, expected versus actual behavior, impact and a workaround; distinguish facts from guesses.
  • thread_id: Existing thread to continue; omit to start a new thread.
  • title: Optional readable title for the message.
  • ping: Session IDs, "all" for active peers, or no recipients. Explicit IDs wake only eligible managed teammates, not independent leaders.
  • idempotency_key: Reuse this key when retrying uncertain IO. The same publication is returned without notifying recipients twice.
  • reply_required: Track an answer obligation for each addressed recipient.
  • reply_to: Explicit unanswered request to answer. A no-ping thread continuation otherwise answers only the latest addressed entry if it is an unanswered request; it never falls back to older requests.
Returns:

CouncilEntry with its entry/thread IDs and per-recipient replies. Pending, delivered and unavailable states are not completed answers. Inspect the entry later with get to see replies and their states.

Each message owns its kind and host-generated source_ref. That reference identifies this publication, not a reported incident: include the original session and turn/iteration/form when reporting one. Failed Python tool executions already have an autocomplain entry; enrich its thread instead of duplicating it. Follow-ups and acknowledgements do not grant wake rights.

def threads( self, *, after: int = 0, limit: int = 50) -> CouncilPage:

List roots and their kind in entry-ID order; replies do not reorder roots.

def read( self, *, thread_id: int | None = None, after: int = 0, limit: int = 50) -> CouncilPage:

Read a bounded page; never consumes or acknowledges a ping.

def get(self, entry_id: int) -> CouncilEntry:

Read the full content behind a preview, in this handle's group.

@dataclass(frozen=True, slots=True)
class CouncilEntry:
CouncilEntry( entry_id: int, kind: Literal['complain', 'coordination', 'informational'], thread_id: int, group_id: str | None, content: str, author_session_id: str, created_at: int, source: str, ping: tuple[str, ...], title: str | None = None, source_ref: CouncilSource | None = None, reply_required: bool = False, reply_to: int | None = None, replies: tuple[CouncilReply, ...] = ())
entry_id: int
kind: Literal['complain', 'coordination', 'informational']
thread_id: int
group_id: str | None
content: str
author_session_id: str
created_at: int
source: str
ping: tuple[str, ...]
title: str | None
source_ref: CouncilSource | None
reply_required: bool
reply_to: int | None
replies: tuple[CouncilReply, ...]
@classmethod
def from_wire(cls, data):
CouncilKind = typing.Literal['complain', 'coordination', 'informational']
@dataclass(frozen=True, slots=True)
class CouncilMember:
CouncilMember(session_id: str, title: str, state: str)
session_id: str
title: str
state: str
@dataclass(frozen=True, slots=True)
class CouncilPage:
CouncilPage( entries: tuple[CouncilEntry | CouncilThread, ...], after: int, has_more: bool)
entries: tuple[CouncilEntry | CouncilThread, ...]
after: int
has_more: bool
@classmethod
def from_wire(cls, data, row, definition):
@dataclass(frozen=True, slots=True)
class CouncilReply:
CouncilReply(session_id: str, state: str, reply_entry_id: int | None = None)
session_id: str
state: str
reply_entry_id: int | None
@dataclass(frozen=True, slots=True)
class CouncilSource:
CouncilSource( session_id: str, turn: int | None, iteration: int | None, form: int | None, operation_id: str | None = None, session_state_id: str | None = None, session_turn_soul_id: str | None = None, session_turn_state_id: str | None = None, session_turn_iteration_id: str | None = None, tool_call_id: str | None = None)
session_id: str
turn: int | None
iteration: int | None
form: int | None
operation_id: str | None
session_state_id: str | None
session_turn_soul_id: str | None
session_turn_state_id: str | None
session_turn_iteration_id: str | None
tool_call_id: str | None
@classmethod
def from_wire(cls, data):
@dataclass(frozen=True, slots=True)
class CouncilThread:
CouncilThread( thread_id: int, kind: Literal['complain', 'coordination', 'informational'], title: str, author_session_id: str, created_at: int)
thread_id: int
kind: Literal['complain', 'coordination', 'informational']
title: str
author_session_id: str
created_at: int
@dataclass(frozen=True, slots=True)
class Event:

Typed envelope yielded by Events; payload fields depend on type.

Attributes:
  • type: Event name identifying how to interpret the payload.
  • session_id: Conversation that emitted the event.
  • seq: Sequence number for a journal event, when supplied.
  • cursor: Replay position from a subscription control event, when supplied.
  • turn_id: Request associated with this event, or None for session events.
  • data: Event-specific dictionary; not a final turn result by itself.
  • activity: Validated activity projection, when this event carries one.
  • view: Validated view event, when this event carries one.

Stream readers validate wire records through from_wire. Use Turn.read or Turn.wait for a request's canonical result instead of treating each event as a completed response.

Event( type: str, session_id: str, seq: int | None = None, cursor: int | None = None, turn_id: str | None = None, data: dict[str, typing.Any] = <factory>, activity: blockether.vis.activity.ActivityProjection | None = None, view: blockether.vis.views.ViewEvent | None = None)
type: str
session_id: str
seq: int | None
cursor: int | None
turn_id: str | None
data: dict[str, typing.Any]
@classmethod
def from_wire(cls, value: Any) -> Event:
class Events(blockether.vis.engine._client._EventStream):

Iterate typed session events, with replay and bounded reconnection.

Obtain a stream from Session.events. It yields Event objects; inspect type, turn_id and the event-specific data rather than parsing raw SSE. The stream covers the whole conversation and does not stop when one turn completes. Use it in a with block or call close when done.

Arguments:
  • session: Conversation whose events you want to follow.
  • cursor: Nonnegative replay position, normally a saved cursor or the cursor from Session.send. Defaults to 0.
  • **options: reconnects bounds retries (default 3); retry_delay is a nonnegative finite delay in seconds (default 0.2).

Duplicate events are suppressed. subscription.ready resets the cursor, including after a daemon restart, so persist the stream's current cursor rather than assuming it is always increasing. The idle timeout is the client's timeout. Closing the stream never cancels a turn. Invalid replay options raise ValueError; malformed events raise ProtocolError.

Events( session: Session, *, cursor=0, **options)
Inherited methods and attributes
client
def close(self):

Release this event subscription without cancelling conversation work.

Close the active response and iterator and detach the stream from its client. Repeated calls are safe; further iteration stops. The client and session remain open. Context exit calls this method automatically.

class ExecutionLayer(abc.ABC):

Shared session API for local processes and explicit gateway connections.

Applications normally choose blockether.vis.engine.LocalEngine or blockether.vis.engine.GatewayClient, then use create_session to start a conversation or session to attach to an existing session ID. Agent wraps this API when you only need one conversation.

The named HTTP methods below expose lower-level engine routes. Their body and query values use the gateway's canonical wire schema, not arbitrary Python objects. Prefer Session and Turn methods for ordinary workflows. Route failures raise GatewayError; IO and malformed replies raise TransportError or its subclasses. Mutations are not automatically retried.

Arguments:
  • timeout: Positive finite transport timeout in seconds; defaults to 30. This is independent of a turn's wait deadline.

Use each layer and its session handles on one calling thread. Context entry calls connect; context exit calls close. A custom transport implements connect, close, session_options and _open. The latter returns a context-managed binary response with status and headers. Path and channel defaults belong to the layer, not to Agent.

timeout
@abstractmethod
def connect(self) -> ExecutionLayer:

Connect or start the layer; repeated calls keep the same connection.

@abstractmethod
def close(self) -> None:

Release this layer's resources without deleting remote sessions.

@abstractmethod
def session_options( self, project='.') -> dict[str, str | int | float | bool | None | list[str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]] | dict[str, str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]]]:

Validate a project and return its wire-ready session creation options.

def session(self, sid: str) -> Session:

Return a lightweight handle for an existing session ID.

This does not fetch or validate the remote session. Use Session.read to retrieve its state; a missing session is reported by that request. The handle borrows this layer and does not own its lifetime.

def create_session( self, *, timeout=None, **options) -> Session:

Create a conversation and return a Session handle.

Arguments:
  • timeout: Optional timeout in seconds for this creation request.
  • **options: Canonical session creation fields. For a project path, pass **layer.session_options(project) so local and gateway path rules and channel defaults are applied correctly.

This sends a creation request immediately. Unlike session, it creates a new record; use the returned handle's id to attach to it later.

def put_session_client_extensions( self, sid: str, *, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')], timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

PUT /v1/sessions/:sid/client-extensions — bind client-owned declarations.

def delete_session_client_extensions( self, sid: str, *, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

DELETE /v1/sessions/:sid/client-extensions — detach owned callbacks.

def get_session_client_calls( self, sid: str, *, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/client-calls — retrieve pending owned calls.

def post_session_client_call_result( self, sid: str, call_id: str, *, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')], timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/sessions/:sid/client-calls/:call_id/result — acknowledge one call.

def post_session_client_call_activity( self, sid: str, call_id: str, *, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')], timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/sessions/:sid/client-calls/:call_id/activity — publish presentation.

def list_sessions(self, **query):

Return one page including next_cursor; no hidden full-fleet fetch.

def get_capabilities( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/capabilities — json response.

def get_devices( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/devices — json response.

def post_devices( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/devices — json response.

def delete_device( self, token: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

DELETE /v1/devices/:token — json response.

def post_devices_test( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/devices/actions/test — json response.

def get_fs( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/fs — json response.

def post_fs_mkdir( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/fs/actions/mkdir — json response.

def get_improve( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/improve — json response.

def post_improve( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/improve — json response.

def get_improve_settings( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/improve/settings — json response.

def patch_improve_settings( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

PATCH /v1/improve/settings — json response.

def post_improve_review( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/improve/review — json response.

def get_improve_entry( self, entry_id: int, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/improve/:id — json response.

def patch_improve_entry( self, entry_id: int, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

PATCH /v1/improve/:id — json response.

def get_mcp_servers( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/mcp/servers — json response.

def post_mcp_servers( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/mcp/servers — json response.

def delete_mcp_server( self, name: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

DELETE /v1/mcp/servers/:name — json response.

def put_mcp_server( self, name: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

PUT /v1/mcp/servers/:name — json response.

def post_mcp_server_enable( self, name: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/mcp/servers/:name/actions/enable — json response.

def post_mcp_server_kill( self, name: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/mcp/servers/:name/actions/kill — json response.

def post_mcp_server_start( self, name: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/mcp/servers/:name/actions/start — json response.

def post_mcp_server_auth_cancel( self, name: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/mcp/servers/:name/auth/cancel — json response.

def post_mcp_server_auth_complete( self, name: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/mcp/servers/:name/auth/complete — json response.

def post_mcp_server_auth_logout( self, name: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/mcp/servers/:name/auth/logout — json response.

def post_mcp_server_auth_poll( self, name: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/mcp/servers/:name/auth/poll — json response.

def post_mcp_server_auth_start( self, name: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/mcp/servers/:name/auth/start — json response.

def post_mcp_servers_test( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/mcp/servers/actions/test — json response.

def get_models( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/models — json response.

def get_projects( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/projects — json response.

def post_projects( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/projects — json response.

def delete_project( self, pid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> None:

DELETE /v1/projects/:pid — empty response.

def get_project( self, pid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/projects/:pid — json response.

def patch_project( self, pid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

PATCH /v1/projects/:pid — json response.

def patch_project_sessions( self, pid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

PATCH /v1/projects/:pid/sessions — json response.

def post_projects_ensure( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/projects/actions/ensure — json response.

def get_projects_overview( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/projects/overview — json response.

def get_provider_presets( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/provider-presets — json response.

def post_providers( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/providers — json response.

def delete_provider( self, provider_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

DELETE /v1/providers/:provider-id — json response.

def post_provider_auth_cancel( self, provider_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/providers/:provider-id/auth/cancel — json response.

def post_provider_auth_complete( self, provider_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/providers/:provider-id/auth/complete — json response.

def post_provider_auth_poll( self, provider_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/providers/:provider-id/auth/poll — json response.

def post_provider_auth_start( self, provider_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/providers/:provider-id/auth/start — json response.

def get_provider_limits( self, provider_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/providers/:provider-id/limits — json response.

def post_provider_reset_credits_consume( self, provider_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/providers/:provider-id/reset-credits/consume — json response.

def post_provider_logout( self, provider_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/providers/:provider-id/logout — json response.

def get_provider_models( self, provider_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/providers/:provider-id/models — json response.

def get_provider_status( self, provider_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/providers/:provider-id/status — json response.

def get_router( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/router — json response.

def patch_router( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

PATCH /v1/router — json response.

def get_sessions( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions — json response.

def post_sessions( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/sessions — json response.

def delete_session( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> None:

DELETE /v1/sessions/:sid — empty response.

def get_session( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid — json response.

def patch_session( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

PATCH /v1/sessions/:sid — json response.

def get_session_activity( self, sid: str, aid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/activity/:aid — a bounded page of complete Activity records.

Query with after, limit and q. Follow history.next_after until null; reject a changed revision when combining pages into one copy.

def get_session_activity_export( self, sid: str, aid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> Response:

GET /v1/sessions/:sid/activity/:aid/export — complete unfiltered Activity text.

The gateway streams this response; the returned Response buffers its bytes. Supply revision to reject a changed history before the export starts. Raises ProtocolError if a concurrent change marks the export incomplete.

def get_session_artifacts( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/artifacts — json response.

def post_session_attachments( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, content: bytes | None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/sessions/:sid/attachments — json response.

def post_session_cancel_current( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/sessions/:sid/cancel-current — json response.

def get_session_context( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/context — json response.

def post_session_drain_queue( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/sessions/:sid/drain-queue — json response.

def get_session_events_since( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/events-since — json response.

def get_session_forks( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/forks — json response.

def post_session_forks( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/sessions/:sid/forks — json response.

def post_session_iteration_attachments( self, sid: str, iid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/sessions/:sid/iterations/:iid/attachments — json response.

def get_session_iteration_attachments( self, sid: str, iid: str, idx: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> Response:

GET /v1/sessions/:sid/iterations/:iid/attachments/:idx — binary response.

def get_session_model( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/model — json response.

def patch_session_model( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

PATCH /v1/sessions/:sid/model — json response.

def post_session_release( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> None:

POST /v1/sessions/:sid/release — empty response.

def get_session_resources( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/resources — json response.

def get_session_resources_logs( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/resources/logs — json response.

def post_session_resources_stop( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/sessions/:sid/resources/stop — json response.

def post_session_resume_queue( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/sessions/:sid/resume-queue — json response.

def get_session_seq( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/seq — json response.

def get_session_slashes( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/slashes — json response.

def post_session_speech( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/sessions/:sid/speech — json response.

def delete_session_speech_job( self, sid: str, job_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

DELETE /v1/sessions/:sid/speech/jobs/:job-id — json response.

def get_session_speech_job( self, sid: str, job_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/speech/jobs/:job-id — json response.

def get_session_speech_job_audio( self, sid: str, job_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> Response:

GET /v1/sessions/:sid/speech/jobs/:job-id/audio — binary response.

def get_session_suggest( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/suggest — json response.

def get_session_transcript( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/transcript — json response.

def get_session_transcript_html( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> Response:

GET /v1/sessions/:sid/transcript.html — html response.

def get_session_transcript_md( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> Response:

GET /v1/sessions/:sid/transcript.md — markdown response.

def get_session_turns( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/turns — json response.

def post_session_turns( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/sessions/:sid/turns — json response.

def delete_session_turn( self, sid: str, tid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

DELETE /v1/sessions/:sid/turns/:tid — json response.

def get_session_turn( self, sid: str, tid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/turns/:tid — json response.

def patch_session_turn( self, sid: str, tid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

PATCH /v1/sessions/:sid/turns/:tid — json response.

def get_session_turn_attachments( self, sid: str, tid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/turns/:tid/attachments — json response.

def post_session_turn_cancel( self, sid: str, tid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/sessions/:sid/turns/:tid/cancel — json response.

def get_session_turn_trace( self, sid: str, tid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/turns/:tid/trace — json response.

def get_session_usage( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/usage — json response.

def post_session_view( self, sid: str, view_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/sessions/:sid/views/:view-id/actions — json response.

def get_session_views_input( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/views/input — json response.

def get_session_views_live( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/views/live — json response.

def get_session_views_live_log( self, sid: str, view_id: str, node_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/views/live/:view-id/log/:node-id — json response.

def post_session_voice( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, content: bytes | None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/sessions/:sid/voice — json response.

def delete_session_voice_job( self, sid: str, job_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

DELETE /v1/sessions/:sid/voice/jobs/:job-id — json response.

def get_session_voice_job( self, sid: str, job_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/voice/jobs/:job-id — json response.

def get_session_workspace( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/sessions/:sid/workspace — json response.

def patch_session_workspace_root( self, sid: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

PATCH /v1/sessions/:sid/workspace/root — json response.

def post_machines_order( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/machines/order — register gateway IDs and return their durable order.

def get_settings( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/settings — json response.

def post_settings( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/settings — json response.

def get_setting( self, id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/settings/:id — json response.

def post_speech( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, body: str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')] = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/speech — json response.

def delete_speech_job( self, job_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

DELETE /v1/speech/jobs/:job-id — json response.

def get_speech_job( self, job_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/speech/jobs/:job-id — json response.

def get_speech_job_audio( self, job_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> Response:

GET /v1/speech/jobs/:job-id/audio — binary response.

def get_speech_model( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/speech/model — json response.

def post_speech_model( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/speech/model — json response.

def get_speech_voices( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/speech/voices — json response.

def post_speech_voices( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, content: bytes | None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/speech/voices — json response.

def delete_speech_voice( self, voice_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

DELETE /v1/speech/voices/:voice-id — json response.

def get_speech_voice_sample( self, voice_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> Response:

GET /v1/speech/voices/:voice-id/sample — binary response.

def post_voice( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None, content: bytes | None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/voice — json response.

def delete_voice_job( self, job_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

DELETE /v1/voice/jobs/:job-id — json response.

def get_voice_job( self, job_id: str, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/voice/jobs/:job-id — json response.

def get_voice_model( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

GET /v1/voice/model — json response.

def post_voice_model( self, *, query: Mapping[str, str | int | float | bool | None] | None = None, timeout: float | None = None) -> str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]:

POST /v1/voice/model — json response.

def speech_events(self, job_id: str, **options) -> JobEvents:

Synthesis snapshots over SSE (HTTP) or bounded polling (local).

def voice_events(self, job_id: str, **options) -> JobEvents:

Transcription snapshots over SSE (HTTP) or bounded polling (local).

def session_speech_events( self, sid: str, job_id: str, **options) -> JobEvents:

Session-scoped synthesis snapshots; close never cancels the job.

def session_voice_events( self, sid: str, job_id: str, **options) -> JobEvents:

Session-scoped transcription snapshots; close never cancels the job.

class GatewayClient(blockether.vis.engine.ExecutionLayer):

Use an existing Vis gateway through an explicit HTTP(S) origin.

Choose this layer when sessions should outlive your Python process or the engine runs on another machine. It never starts or discovers a gateway and never reads locally saved credentials. Obtain an authorized gateway URL and token separately; keep tokens out of source code and logs.

Arguments:
  • url: HTTP(S) origin such as https://gateway.example.com, without a path, query, fragment or embedded credentials.
  • token: Optional bearer token supplied by your application.
  • timeout: Positive finite transport timeout in seconds; defaults to 30.

Construction makes no network request. Context entry calls connect to check protocol compatibility and acquire a client lease. Closing releases this client's lease and streams, not the gateway or its stored sessions. Reuse the same layer for multiple agents, then close it after those agents.

import os
from blockether.vis.engine import Agent, GatewayClient

with GatewayClient(
    "https://gateway.example.com", token=os.environ["VIS_GATEWAY_TOKEN"]
) as layer:
    with Agent(project="/workspace/project", execution_layer=layer) as agent:
        result = agent.run("Summarize this project without changing files.")
        print(result["status"])

The project path is absolute and belongs to the gateway machine, not this Python process. TLS certificate verification is enabled; redirects are refused so credentials cannot follow them to another origin. Each instance and its session handles use one calling thread. HTTP failures raise GatewayError; connection, deadline and protocol failures use the TransportError exception family.

GatewayClient(url: str, *, token: str | None = None, timeout: float = 30)
def connect(self) -> GatewayClient:

Check protocol compatibility and acquire this client's lease once.

Return this client. Repeated calls reuse its lease. An incompatible gateway raises ProtocolError; authentication and other HTTP failures raise GatewayError. A failed keepalive requires a new client rather than silently resuming work under a different lease.

def close(self) -> None:

Close streams and release this client's lease without stopping the gateway.

Stored remote sessions are not deleted. Repeated calls are safe, but this closed client cannot be reused. Use Turn.cancel when you need explicit cancellation rather than merely detaching a client.

def session_options( self, project='.') -> dict[str, str | int | float | bool | None | list[str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]] | dict[str, str | int | float | bool | None | list[ForwardRef('JSONValue')] | dict[str, ForwardRef('JSONValue')]]]:

Prepare an app-channel session using a path on the gateway machine.

Inherited methods and attributes

Inherited from ExecutionLayer.timeout.

Inherited from ExecutionLayer.session.

Inherited from ExecutionLayer.get_devices.

Inherited from ExecutionLayer.post_devices.

Inherited from ExecutionLayer.get_fs.

Inherited from ExecutionLayer.get_improve.

Inherited from ExecutionLayer.post_improve.

Inherited from ExecutionLayer.get_improve_entry.

Inherited from ExecutionLayer.patch_improve_entry.

Inherited from ExecutionLayer.get_models.

Inherited from ExecutionLayer.get_projects.

Inherited from ExecutionLayer.get_project.

Inherited from ExecutionLayer.get_router.

Inherited from ExecutionLayer.patch_router.

Inherited from ExecutionLayer.get_sessions.

Inherited from ExecutionLayer.get_session.

Inherited from ExecutionLayer.get_settings.

Inherited from ExecutionLayer.get_setting.

Inherited from ExecutionLayer.post_speech.

Inherited from ExecutionLayer.post_voice.

Inherited from ExecutionLayer.voice_events.

class GatewayError(builtins.RuntimeError):

HTTP failure; status and code are safe to inspect without logging bodies.

GatewayError(status: int, code: str)
status
code
@dataclass(frozen=True, slots=True)
class JobEvent:

Current speech job snapshot, not a session event or a replay cursor.

JobEvent( type: str, id: str, phase: str, is_done: bool, data: dict[str, typing.Any] = <factory>)
type: str
id: str
phase: str
is_done: bool
data: dict[str, typing.Any]
class JobEvents(blockether.vis.engine._client._EventStream):

Snapshot-first job SSE; reconnect rereads state, terminal is_done ends it.

Job streams have no cursor and make no exactly-once claim. Identical snapshots are suppressed within this iterator. Remaining fields retain the canonical JSON.

JobEvents(client, route, job_id, event_name, **options)
Inherited methods and attributes
client
def close(self):

Release this event subscription without cancelling conversation work.

Close the active response and iterator and detach the stream from its client. Repeated calls are safe; further iteration stops. The client and session remain open. Context exit calls this method automatically.

JSONValue = str | int | float | bool | None | list['JSONValue'] | dict[str, 'JSONValue']

Own a private Vis process without starting an HTTP server.

Use this layer when you need to choose an executable, share one local process between agents, or call the session API directly. The Vis executable must be installed separately; this class never downloads it or discovers a gateway. Supported platforms are Linux and macOS.

Arguments:
  • executable: Executable path/name or nonempty argument sequence. The SDK appends sdk-stdio; no shell command parsing is performed.
  • root: Existing local working directory, resolved at construction.
  • timeout: Positive finite timeout in seconds for each transport operation.
  • startup_timeout: Positive finite deadline in seconds for initial boot.

Construction is lazy. connect or context entry starts the subprocess; repeated connection calls reuse it. close stops only this owned process and discards its temporary session database. It does not revert project edits or stop any separately running Vis server. Explicitly injected agents borrow this layer, so close those agents before leaving the layer's context.

from blockether.vis.engine import Agent, LocalEngine

with LocalEngine(executable="vis-agent", root=".") as layer:
    with Agent(project=".", execution_layer=layer) as agent:
        result = agent.run("Summarize this project without changing files.")
        print(result["status"])

A pipe timeout stops the process: a late reply must never be mistaken for the next request's answer. This differs from a blockether.vis.engine.Turn.wait deadline, which does not itself request cancellation. Startup, protocol and transport failures propagate as the corresponding engine exception.

LocalEngine(*, executable='vis-agent', root='.', timeout=30, startup_timeout=120)
def session_options(self, project='.') -> dict:

Resolve an existing local directory before the caller changes directory.

def connect(self):

Start the owned process once and validate its protocol handshake.

Return this layer for chaining. A closed layer cannot be restarted; create a new one after failure or closure. Startup failure cleans up the process and temporary database before propagating the error.

def session(self, sid):

Return a lightweight handle for an existing session ID.

This does not fetch or validate the remote session. Use Session.read to retrieve its state; a missing session is reported by that request. The handle borrows this layer and does not own its lifetime.

def close(self):

Stop this process, close its streams and remove its temporary database.

Repeated calls are safe, including retrying cleanup after a signal fails. A failed close still prevents new requests. Unfinished local work cannot continue after the process stops. File edits and separately running gateways are untouched.

Inherited methods and attributes

Inherited from ExecutionLayer.timeout.

Inherited from ExecutionLayer.get_devices.

Inherited from ExecutionLayer.post_devices.

Inherited from ExecutionLayer.get_fs.

Inherited from ExecutionLayer.get_improve.

Inherited from ExecutionLayer.post_improve.

Inherited from ExecutionLayer.get_improve_entry.

Inherited from ExecutionLayer.patch_improve_entry.

Inherited from ExecutionLayer.get_models.

Inherited from ExecutionLayer.get_projects.

Inherited from ExecutionLayer.get_project.

Inherited from ExecutionLayer.get_router.

Inherited from ExecutionLayer.patch_router.

Inherited from ExecutionLayer.get_sessions.

Inherited from ExecutionLayer.get_session.

Inherited from ExecutionLayer.get_settings.

Inherited from ExecutionLayer.get_setting.

Inherited from ExecutionLayer.post_speech.

Inherited from ExecutionLayer.post_voice.

Inherited from ExecutionLayer.voice_events.

class ProtocolError(blockether.vis.engine.TransportError):

Peer is incompatible or returned malformed protocol data.

Query = collections.abc.Mapping[str, str | int | float | bool | None]
@dataclass(frozen=True, slots=True)
class Response:

Response bytes with their status and headers, before content decoding.

Returned by binary and transcript APIs. Use content directly for files, inspect headers for their media type, or call json for JSON transcripts. json raises ProtocolError for malformed or non-JSON content.

Response(status: int, content: bytes, headers: dict[str, str])
status: int
content: bytes
headers: dict[str, str]
def json(self) -> Any:

Decode content as JSON, or raise ProtocolError if it is invalid.

@dataclass(frozen=True, slots=True)
class Session:

A conversation handle bound to one execution layer and session ID.

Obtain it from Agent.session, ExecutionLayer.create_session or ExecutionLayer.session. Constructing a handle does not read the session. It borrows the layer; keep the layer open while using it.

Use send for a new turn and turns for history. read fetches current session state. events follows progress; input_views and answer let your application handle pending human input. transcript, artifacts, upload and download_attachment cover content exchange. council binds messaging and managed-agent controls to this conversation.

Requests return canonical dictionaries unless a method documents a typed handle or Response. HTTP errors raise GatewayError, including missing or inaccessible session IDs; no method automatically retries mutations.

Session(client: ExecutionLayer, id: str)
client: ExecutionLayer
id: str
def council(self, *, group_id: str | None = None):

Bind communication to the current run without blocking session-only controls.

Disabled or unavailable Council groups are reported when using communication or group_id. Successful bindings retain their acquisition-time activation.

def read(self):

Fetch the current canonical session record as a dictionary.

Pending application-owned tool calls are serviced on the calling thread before fetching state. This is a fresh read, not a cached snapshot.

def update(self, **fields):

Patch canonical session fields and return the engine's JSON response.

Field names and validation follow the gateway session-update contract; unknown or invalid fields are rejected by the engine.

def delete(self):

Ask the engine to delete this conversation and return its response.

This is a destructive session operation, not a connection close. It does not undo changes already made to project files. Do not use this handle for further conversation requests after successful deletion.

def turns(self, **query):

Read turn history, or the queued subset with status='queued'.

def artifacts(self, **query):

Return the gateway's artifact inventory without downloading its bytes.

def transcript( self, *, format: str = 'json', **query) -> Response:

Read a JSON, Markdown or HTML transcript, preserving bytes and headers.

def upload(self, content: bytes, *, filename: str, media_type: str):

Upload bytes; pass the returned upload_id in send(attachments=[...]).

def download_attachment( self, iteration_id: str, index: int) -> Response:

Download one persisted iteration attachment without decoding binary data.

def goal( self, objective: str, *, iteration_budget: int | None = None, **options) -> Turn:

Submit an explicit goal through /goal and return its execution Turn.

No goal is inferred from ordinary messages. Read its state in read()['goal']. Pause/resume/cancel use send('/goal --pause'), --resume or --cancel. The optional budget counts loop iterations, including prose and empty replies. The last iteration may run its tools; the limit blocks the next model request. Token usage is recorded only as a statistic.

def send( self, request: str, *, idempotency_key: str | None = None, **options) -> Turn:

Submit a user message or slash command and return its Turn handle.

Arguments:
  • request: Message text sent to this conversation.
  • idempotency_key: Stable key for retrying the same submission after uncertain IO. Omission creates a new key for each call.
  • **options: Canonical turn submission fields such as provider, model and attachments. Upload attachment bytes first with upload and pass the returned upload IDs in attachments.

Return does not mean the model has finished: use Turn.wait or Turn.read. The returned cursor marks the event position before this submission; pass it to events to follow subsequent progress. Model requests may incur costs and change project files. Submission failures propagate; the SDK never automatically retries this mutation.

def input_views(self) -> list[blockether.vis.views.InputView]:

Read pending input requests as typed blockether.vis.views.InputView records.

Use their view IDs with answer to submit values. An empty list means no input requests were returned in this snapshot.

def live_views(self) -> list[blockether.vis.views.LiveView]:

Read current live views as typed blockether.vis.views.LiveView records.

This fetches a snapshot rather than subscribing to future updates; use events to follow view events. Malformed view data raises ProtocolError.

def view_action(self, view_id: str, action: str, **values):

Send an operator action to a view and return the engine's JSON response.

values supplies the action-specific fields of the canonical operator action schema. The request is validated before submission. Use answer for the common case of submitting input values.

def answer(self, view_id, values):

Submit input values to a view, returning the engine's response.

Pass a view ID from input_views and values matching that input request. This is shorthand for view_action(view_id, "submit", values=values).

def events(self, **options) -> Events:

Follow this conversation's progress as an iterable of Event records.

Options are cursor (nonnegative replay position, default 0), reconnects (default 3) and retry_delay (seconds, default 0.2). Use a context manager to close the stream when you stop iterating. The stream spans the conversation, not just one turn; filter turn_id when tracking a specific request. Closing it does not cancel work.

Gateway sessions normally use SSE. Local execution and application-owned callbacks use finite event-page polling so Python callbacks run on the calling thread. Both expose the same event interface.

class TransportError(builtins.RuntimeError):

Connection failed or the client has been closed.

@dataclass(frozen=True, slots=True)
class Turn:

Handle for one submitted request, independent of other session turns.

Returned by Agent.send or Session.send. id identifies this request; cursor is the session event position captured before submission. The handle borrows its session and execution layer. Keep that layer open while calling read, wait or cancel.

Turn( session: Session, id: str, cursor: int = 0)
session: Session
id: str
cursor: int
def read(self, *, timeout=None):

Fetch this turn's current canonical record, including its status.

timeout optionally overrides this request's transport deadline in seconds. Application-owned callbacks are serviced before reading state.

def cancel(self):

Request cancellation of this turn and return the engine's response.

Use read or wait to inspect the resulting status. Cancellation does not revert file edits or other side effects already performed.

def wait(self, *, timeout: float = 300):

Poll this turn until it finishes or suspends, returning its record.

Arguments:
  • timeout: Positive finite overall wait deadline in seconds.
Returns:

A canonical dictionary whose status is completed, failed, cancelled, suspended or error. A failure status is data, not a raised model-work exception; inspect it before using the result.

Raises:
  • VisTimeout: The deadline expired. This method does not request cancellation; you can wait again or explicitly call cancel.

Transport and HTTP errors also propagate. For a local engine, a timeout of the underlying pipe operation closes that process to prevent replies getting out of order; this is distinct from merely ending the poll loop.

Deadline expired; the remote operation may still be running.