Skip to main content
Functions are Python code that runs in isolated Docker containers. They can be used as agent tools, triggered by webhooks or schedules, or executed directly. Key properties:

Function signature

The entry point must be named handler. It receives two arguments — input_data (validated against input_schema) and context (execution metadata):
Legacy: Functions named after the resource name (e.g. def send_email(input_data, context)) still work but log a deprecation warning. Migrate to def handler(...).
The access_token lets functions call back into the Sinas API with the triggering user’s identity — useful for reading state, triggering other functions, or accessing any other endpoint.

Trigger-specific input_data

Depending on how the function is invoked, input_data is populated differently:

Hook function return values

Functions used as message hooks (configured in agent’s hooks field) can return: Async hooks run fire-and-forget. For on_assistant_message async hooks, the return value retroactively updates the stored message (not the already-streamed response).

Interactive input (shared containers only)

Functions running in shared containers (shared_pool=true) can call input() to pause and wait for user input:
When input() is called:
  1. The execution status changes to AWAITING_INPUT with the prompt string
  2. The function thread blocks until a resume value is provided
  3. The calling agent or API client resumes execution with the user’s response
  4. Multiple input() calls are supported (each triggers a new pause/resume cycle)
In sandbox containers (shared_pool=false), calling input() raises a RuntimeError. Execution: Functions run in pre-warmed Docker containers from a managed pool. Input is validated before execution, output is validated after. All executions are logged with status, duration, input/output, and any errors.
Nested executions are depth-limited. A function can invoke other functions or agents (e.g. by calling the Sinas API with its execution token). Such chains are bounded by MAX_EXECUTION_DEPTH (defaults to the shared worker count): a call past the limit is rejected immediately rather than silently exhausting the shared worker pool and deadlocking. Keep shared_pool functions shallow, or raise SHARED_POOL_RESERVE / scale workers if you intentionally nest deeply. See environment variables.
Endpoints: