Skip to main content

Sirapana Ai Engine

Project description

PyRuntime — Python API Reference

PyRuntime is the Python-facing async interface to the soulengine Rust core. Exposed via a PyO3 extension module, it manages the full lifecycle of users, agents, topic threads, and message memory.


Contents


Installation & Import

from soulengine import PyRuntime

Windows: Ensure PyTorch's DLL directory is added before importing.

import torch, os
os.add_dll_directory(os.path.join(os.path.dirname(torch.__file__), "lib"))
from soulengine import PyRuntime

Initialisation

PyRuntime.create(bind="127.0.0.1:3077")PyRuntime

Creates and returns a new PyRuntime instance. This is the only constructor — do not call PyRuntime() directly. Also launches the HTTP API server at the given bind address.

runtime = await PyRuntime.create(bind="127.0.0.1:3077")

This is a staticmethod and must be awaited. It initialises the internal Rust Runtime wrapped in Arc<RwLock<>>.

Reads two config files at startup — both must exist and be valid:

configs/
├── inference_config.toml
└── agents_config.toml

User Management

create_user(user_name: str)str

Registers a new user identity and returns a unique user_id.

user_id = await runtime.create_user("kattalaiUser")
Parameter Type Description
user_name str Display name for the user

Returns: str — opaque user ID, required for insert_message.


Topic Threads

A topic thread is the shared conversation context that users and agents read from and write to.

create_topic_thread()str

Creates a new topic thread and returns its topic_id.

topic_id = await runtime.create_topic_thread()

topic_history_len(topic_id: str)int

Returns the total number of messages in the thread. Use this for polling — compare before and after insert_message to detect new activity.

length = await runtime.topic_history_len(topic_id)

iter_topic(topic_id: str, start_index: int)str (JSON)

Returns a JSON-serialised list of messages from start_index onward.

raw     = await runtime.iter_topic(topic_id, cursor)
entries = json.loads(raw)   # list of dicts

Each entry contains:

Key Type Description
name str Source name (agent name or user handle)
role str "user" or "assistant"
content str Raw message text (may contain block markers)

Incremental polling pattern:

# Snapshot length before sending
cursor = await runtime.topic_history_len(topic_id)

# ... send message, wait ...

# Fetch only new entries
new_entries = json.loads(await runtime.iter_topic(topic_id, cursor))

insert_message(topic_id: str, user_id: str, message: str)str

Inserts a user message into the thread. This triggers attached agents to begin processing.

await runtime.insert_message(topic_id, user_id, "Summarise my unread emails")
Parameter Type Description
topic_id str Target topic thread
user_id str Sender identity (from create_user)
message str Message text

Returns: str — confirmation from the Rust layer.
Raises: ValueError if the insert fails.


Agent Management

get_agent_list()list[str]

Returns the list of agent names registered in the config.

agents = await runtime.get_agent_list()
# e.g. ["Researcher", "Coder", "DIA"]

deploy_agent(agent_name: str)str

Deploys a named agent and returns its agent_id.

agent_id = await runtime.deploy_agent("Researcher")
Parameter Type Description
agent_name str Must match a name in get_agent_list()

Returns: str — opaque agent ID used in topic and episode calls.


add_agent_to_topic(topic_id: str, agent_id: str)str

Attaches an agent to a topic thread. The agent begins responding to new messages inserted into that topic.

await runtime.add_agent_to_topic(topic_id, agent_id)

Only one agent should be active on a topic at a time. Call remove_agent_from_topic before switching agents.

Returns: str — confirmation. Raises: ValueError on failure.


remove_agent_from_topic(topic_id: str, agent_id: str)str

Detaches an agent from a topic thread.

await runtime.remove_agent_from_topic(topic_id, agent_id)

Returns: str — confirmation. Raises: ValueError on failure.


is_agent_working_on_topic(topic_id: str, agent_id: str)bool

Returns True if the agent is currently processing a message. Use this to drive a "thinking…" indicator.

thinking = await runtime.is_agent_working_on_topic(topic_id, agent_id)

Agent Episodes (Internal Memory)

An episode is the agent's internal working scratchpad for a topic — thoughts, tool calls, and intermediate outputs, separate from the shared topic history.

agent_episode_len(topic_id: str, agent_id: str)int

Returns the number of entries in the agent's episode memory.

ep_len = await runtime.agent_episode_len(topic_id, agent_id)

iter_agent_episode(topic_id: str, agent_id: str, start_index: int)str (JSON)

Returns a JSON-serialised list of the agent's internal episode entries from start_index onward. Same shape as iter_topic entries (name, role, content). The content field contains structured response blocks.

raw     = await runtime.iter_agent_episode(topic_id, agent_id, cursor)
entries = json.loads(raw)

Block Format

Agent content fields use fenced-block conventions that the UI layer parses:

```thoughts
Agent reasoning goes here...
```

```terminal
&app_handle command arg
-> result
```

```output
Final response to the user.
```

```validation
Cross-check notes.
```

```followup_context
Handoff state for the next turn.
```

Parser:

import re

def parse_se_content(content: str) -> list[tuple[str, str]]:
    pattern = re.compile(
        r'```(thoughts|terminal|output|validation|followup_context)\s*\n(.*?)```',
        re.DOTALL
    )
    matches = pattern.findall(content)
    if matches:
        return [(kind.strip(), body.strip()) for kind, body in matches if body.strip()]
    return [("output", content.strip())]  # plain-text fallback

Configuration Reference

Both files are read once inside PyRuntime.create(). Changes require a runtime restart — there is no hot-reload.

inference_config.toml

[[ollama_config]]
chat_api_url     = "http://localhost:11434/api/chat"
generate_api_url = "http://localhost:11434/api/generate"
temperature      = 0.1

[[gemini_config]]
api_key     = "YOUR_GEMINI_API_KEY"
temperature = 0.1

[[huggingface_config]]
api_key        = "YOUR_HF_API_KEY"
max_new_tokens = 8000
temperature    = 0.1

[[sarvam_config]]
api_key          = "YOUR_SARVAM_API_KEY"
max_new_tokens   = 8000
temperature      = 0.1
reasoning_effort = "high"
inference_provider Notes
ollama Local inference, no API key. Requires Ollama on localhost:11434.
gemini Google Gemini API. Requires api_key.
huggingface HuggingFace Inference Router. Requires api_key.
sarvam Sarvam AI API. Requires api_key.

Minimum local-only config:

[[ollama_config]]
chat_api_url     = "http://localhost:11434/api/chat"
generate_api_url = "http://localhost:11434/api/generate"
temperature      = 0.1

agents_config.toml

[[agent_config]]
agent_name = "DIA"
agent_goal = "To assist user with their queries"
backstory  = "You are an AI assistant"

reasoning_model = { inference_provider = "ollama", model_id = "qwen3:4b" }
nlp_model       = { inference_provider = "ollama", model_id = "qwen3:0.6b" }
default_apps    = ["clock_app"]
Field Type Description
agent_name str Name passed to deploy_agent() and returned by get_agent_list()
agent_goal str Injected into the agent's system prompt as its objective
backstory str Additional persona context in the system prompt
reasoning_model inline table Provider + model ID for the main thinking loop
nlp_model inline table Provider + model ID for fast NLP/routing decisions
default_apps list[str] App handles loaded on deploy — must match app_handle_name in app TOMLs

Mixing providers per agent:

reasoning_model = { inference_provider = "gemini", model_id = "gemini-2.5-flash" }
nlp_model       = { inference_provider = "ollama", model_id = "qwen3:0.6b" }

App TOML Schema

The app_handle_name in an app's TOML is the string referenced in default_apps.

app_name          = "Clock App"
app_path          = "./apps/core_apps/clock_app/clock_app.py"
app_start_command = "python"
app_start_args    = "./apps/core_apps/clock_app/clock_app.py"
app_handle_name   = "clock_app"
app_launch_mode   = "REPL"

app_usage_guideline = """
Use to get the current time or set timed reminders.
"""

[[app_command_signatures]]
command  = "get_time"
consumes = []
produces = ["current_time"]
action   = "read"

Built-in handle names (available after kattalai-setup):

Handle Description
clock_app Current time and alarms
notes_app Note CRUD and search
grep_app File and stdin search
calculator_app Arithmetic and variables
stock_tracker Live quotes via yfinance
webpage_reader Web extraction via Playwright

Typical Usage Pattern

import asyncio, json
from soulengine import PyRuntime

async def main():
    # 1. Bootstrap
    runtime  = await PyRuntime.create()
    user_id  = await runtime.create_user("alice")
    topic_id = await runtime.create_topic_thread()

    # 2. Deploy and attach an agent
    agents   = await runtime.get_agent_list()
    agent_id = await runtime.deploy_agent(agents[0])
    await runtime.add_agent_to_topic(topic_id, agent_id)

    # 3. Snapshot cursor, send message
    cursor = await runtime.topic_history_len(topic_id)
    await runtime.insert_message(topic_id, user_id, "Hello!")

    # 4. Poll until the agent finishes
    while await runtime.is_agent_working_on_topic(topic_id, agent_id):
        await asyncio.sleep(0.5)

    # 5. Fetch new messages
    entries = json.loads(await runtime.iter_topic(topic_id, cursor))
    for entry in entries:
        if entry["role"] != "user":
            print(f"{entry['name']}: {entry['content']}")

asyncio.run(main())

Error Handling

All PyRuntime methods raise ValueError on internal Rust errors.

try:
    await runtime.insert_message(topic_id, user_id, text)
except ValueError as e:
    print(f"SoulEngine error: {e}")

Thread Safety

The Rust runtime uses Arc<RwLock<Runtime>> internally.

Operations Lock type
create, deploy_agent, create_user, create_topic_thread Write lock
insert_message, iter_topic, topic_history_len, all reads Read lock

All methods are async — use with asyncio or an async framework like textual. Do not share a PyRuntime instance across threads without an async executor.

Project details


Download files

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

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

kattalai-0.4.1.3-cp312-cp312-win_amd64.whl (24.6 MB view details)

Uploaded CPython 3.12Windows x86-64

kattalai-0.4.1.3-cp312-cp312-macosx_11_0_arm64.whl (24.1 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

kattalai-0.4.1.3-cp311-cp311-win_amd64.whl (24.6 MB view details)

Uploaded CPython 3.11Windows x86-64

kattalai-0.4.1.3-cp311-cp311-macosx_11_0_arm64.whl (24.1 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

kattalai-0.4.1.3-cp310-cp310-win_amd64.whl (24.6 MB view details)

Uploaded CPython 3.10Windows x86-64

kattalai-0.4.1.3-cp310-cp310-macosx_11_0_arm64.whl (24.1 MB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

kattalai-0.4.1.3-cp39-cp39-win_amd64.whl (24.6 MB view details)

Uploaded CPython 3.9Windows x86-64

kattalai-0.4.1.3-cp39-cp39-macosx_11_0_arm64.whl (24.1 MB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

File details

Details for the file kattalai-0.4.1.3-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for kattalai-0.4.1.3-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 07dcdac3f0208f7a80f4cdac4504a8b3742e66ef63df6376b9cf0a1fc8e03a03
MD5 746758e58707d194d5a5f143b55ad6ec
BLAKE2b-256 f739109ffa39947bda1374c541ecab4c2d657e8f90b905fde3eb8176393e6d02

See more details on using hashes here.

File details

Details for the file kattalai-0.4.1.3-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for kattalai-0.4.1.3-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 91ec977f67d6a3d137907003a09fa98a80fc38df27c37e2d70d8b2b3032c62f4
MD5 30e310706baf27fb2fc9a47eb79e798f
BLAKE2b-256 07bb959575905aa43a1ff7bc0a8317840aa655e16ca6c6e2a3dd1fe5904ee365

See more details on using hashes here.

File details

Details for the file kattalai-0.4.1.3-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for kattalai-0.4.1.3-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 cce79b21b813ccbac45275be61a0c1fa814c491d1d5e4e3de78a6466c60ab7c6
MD5 694107a792f45fc7c780a0c8751bde06
BLAKE2b-256 54845bf6286e21c07135add979fa9b28917edeaf6acbc2b31af48a6fd0446090

See more details on using hashes here.

File details

Details for the file kattalai-0.4.1.3-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for kattalai-0.4.1.3-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1502bd6a41bee930257ed4eae2c1a036fdef6bb26396154ba61399eddeb29806
MD5 d18cf0f0d55f763a250b47a53118584f
BLAKE2b-256 7c5db662362f197633d4e1c5f2d597f9f0bb753675301d4f64dca119f5f67333

See more details on using hashes here.

File details

Details for the file kattalai-0.4.1.3-cp310-cp310-win_amd64.whl.

File metadata

File hashes

Hashes for kattalai-0.4.1.3-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 d1279e2ca338f3d5d20046fe3aeeb303f9688a930d436739b48141ece2601aec
MD5 4b4fec5861ed626f0536b51d03fd45fe
BLAKE2b-256 57c853ffb0a0cb10e579afdbf732399a85fb01deb0448d84f9b2ec70fa0484a1

See more details on using hashes here.

File details

Details for the file kattalai-0.4.1.3-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for kattalai-0.4.1.3-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 570bc740f6582204a3e52b0cddf7dc8a85478a87a2076c6eed10d4909486c914
MD5 6da96f8305a32f907af668d1ffcc5f3c
BLAKE2b-256 8b036daa283b05ef448d15adc6166043798fa4e2c0be87207c7fc1891398c987

See more details on using hashes here.

File details

Details for the file kattalai-0.4.1.3-cp39-cp39-win_amd64.whl.

File metadata

File hashes

Hashes for kattalai-0.4.1.3-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 e2dc107bc4c0af4d834acd9847faeb53bedf0add0f3664906593dfd220eb17f8
MD5 b9c0aea328cb5240d0c80cbfa79a0ba4
BLAKE2b-256 272e6f271cafb670be29925333727a5e96c94fe2af4c37b7ea698c7fdd1c516a

See more details on using hashes here.

File details

Details for the file kattalai-0.4.1.3-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for kattalai-0.4.1.3-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4c4f34a4cd86a617d9ad5f856424a10b5905c9e71a1d7092f9c9dbb29c0a0f56
MD5 9e1ebca2e565db5913e6ad369f5fa154
BLAKE2b-256 c44bda1b529b7079f7c109af3affe7d98c3dfd10d3a736315de95628e2512c2f

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