retoor # tai tai is a single-file autonomous AI agent written in Python. The entire implementation lives in `tai.py` (about 2000 lines) and uses only the Python standard library: no dependencies, no install step, no build system. The agent runs as an interactive REPL or as a one-shot command. It reasons through an OpenAI-compatible backend, acts through fourteen tools, keeps per-profile memory, seals its stored state at rest, and can isolate shell and file operations inside a container sandbox. ## Requirements - Python 3.10 or newer, no third-party packages. - Optional: `podman` or `docker` for the sandbox and Telegram voice notes. - Optional: `tmux` for terminal content capture. ## Quick start ./tai.py ./tai.py --profile work ./tai.py --yes ./tai.py --version ./tai.py what is 2+3, use the shell Trailing arguments form a one-shot prompt: the agent answers once and exits with code 0. Without arguments, tai starts an interactive session. ## REPL commands | Command | Effect | |-------------------|---------------------------------------------------| | `/profile [name]` | Show the current profile or switch to it | | `/profiles` | List all profiles, current marked with `*` | | `/env [target]` | Show or switch execution environment | | `/skills` | List loaded skill files | | `/fork ` | Spawn a background subagent, REPL stays free | | `/agents` | List background subagents | | `/agent ` | Show one subagent result | | `/agent clear` | Purge finished subagents | | `/compact` | Compress history into a summary | | `/clear` | Drop history, keep the system message | | `/help` | Show the command overview | | `/quit` | Exit | Any other input is sent to the agent. ## Installation ./tai.py --install This copies `tai.py` to `~/.local/bin/tai.py` as an executable and registers a guarded `command_not_found_handle` block in `~/.bashrc` (backed up once to `~/.bashrc.bak-tai`, idempotent), so unknown shell commands are answered by the agent instead of failing. ## Backends The primary backend is `model.cloud.pravda.education`, an OpenAI-compatible gateway that needs no API key and selects a free model per request. If a request fails, tai retries it on `devplace.net/openai/v1`, which requires `DEVPLACE_API_KEY`. Both endpoints speak `/chat/completions`, including native tool calls and streaming. ## Orchestration `/fork ` spawns a background subagent with its own context while the REPL stays free (the prompt shows a `+N` counter). `/agents` lists workers, `/agent ` shows a result, `/agent clear` purges finished ones. The model itself orchestrates through the `fork` tool (task, timeout up to one hour, profile) and the `poll` tool (id, wait up to two minutes). Workers get 12 steps, a cooperative deadline, no session writes, and no interactive approval prompts. Nesting is capped at two levels. Timeouts and errors surface as statuses, never silently. ## Tools | Tool | Purpose | |------------------------------|------------------------------------------------------| | `shell` | Run a shell command, output truncated | | `read_file` | Read a text file, large files truncated | | `write_file` | Write content to a file, creating parent directories | | `edit_file` | Replace one unique exact text match in a file | | `web_search` | Search the web, optionally images or page content | | `web_fetch` | Fetch a URL and return its text content | | `speak` | Synthesize speech, save MP3, play when possible | | `listen` | Record from the microphone and transcribe it | | `remember` | Merge knowledge into the profile system message | | `recall` | Search past session memory by keyword | | `load_skill` | Load a skill file by name | | `get_current_terminal_content` | Capture the current tmux pane with scrollback | | `fork` | Spawn a background subagent | | `poll` | Collect a background subagent result | Web search runs on `rsearch.app.molodetz.nl`. Destructive shell commands ask for confirmation unless `--yes` is given; read-only commands run directly. ## Skills Standard agent skill files (`SKILL.md` with `name` plus `description` frontmatter, optional `scripts/`, `references/`, `assets/`, per the Agent Skills open format) are discovered in `~/.tai/skills/*/` and `./.tai/skills/*/` (project wins on name collisions). Descriptions stay in context; the agent loads full instructions through `load_skill` only when needed. `/skills` lists what is available. ## Sandbox `/env` shows the execution environment, `/env sandbox` switches shell and file tools into an isolated `tai-box` container (podman or docker, no mounts, no shared filesystem), `/env home` switches back. The image is built automatically on first use from an embedded Containerfile; every pip requirement (`faster-whisper`, `edge-tts`) lives inside the image while `tai.py` itself stays dependency-free. Sandbox commands need no approval because the container is disposable. ## Telegram ./tai.py --install-telegram ./tai.py --uninstall-telegram Install asks for the bot token up front, verifies it against `getMe`, stores it in `~/.tai/telegram.env` (0600), builds the sandbox container (used for voice transcription), and registers a `tai-telegram.service` systemd user unit with linger enabled (failures ignored). The bot long-polls, answers text, transcribes voice notes, and understands `/new`. It runs without `--yes`, so destructive shell commands are denied. Uninstall stops and removes the service and purges the container and image; the token file and data stay. ## Profiles and memory Each profile owns a system message plus session history under `~/.tai/profiles`, stored with mode 0600. /profile show current profile /profile [name] switch profile, creating it when missing /profiles list all profiles The `remember` tool merges an instruction into the current profile system message through the model itself: it adds facts, updates behavior, or removes forgotten items while preserving the rest. It fires by default on new passwords and behavior changes. `recall` searches the per-profile episodic log in `~/.tai/memory.db` (SQLite). Context is budgeted at roughly 32k tokens with automatic compaction at 80 percent. ## Sealed storage Storage is sealed by default with a built-in key, which stops casual reads but not a determined attacker, since the key ships in the source. Set `TAI_PASSPHRASE` for real protection: a home sealed with the default key is re-sealed to your passphrase automatically on first boot, with a notice. The key comes from PBKDF2-SHA256 (200k rounds) over a random salt in `~/.tai/.seal`; values use a per-value nonce with HMAC-SHA256 encrypt-then- MAC. SQLite access goes through custom `tai_enc`/`tai_dec` functions registered with `create_function`, so inserts encrypt inline and recall decrypts before matching. Existing plaintext data is sealed automatically on first sealed start. A wrong passphrase refuses to start with exit code 2. Set the variable empty for plaintext storage. This construction uses only the standard library and is honest file-theft protection, not audited cryptography; high-value secrets still belong in a dedicated manager. ## Voice `speak` synthesizes free neural speech via the Microsoft Edge Read Aloud protocol, implemented with `socket` and `ssl` from the standard library. No key, no package. MP3 files land in `~/.tai/audio` and play when an OS player exists. `listen` records and transcribes when a recorder (`arecord`, `sox`, `ffmpeg`) and a transcriber (`whisper-cpp`, `whisper`) are installed, and reports exactly what is missing otherwise. ## Configuration | Variable | Purpose | Default | |---------------------|--------------------------------------|--------------------------------------------| | `TAI_HOME` | State directory | `~/.tai` | | `TAI_MODEL` | Model id, ignored by primary gateway | `openrouter/free` | | `DEVPLACE_API_KEY` | Fallback backend credential | Empty, fallback disabled | | `TAI_VOICE` | Edge voice name | `en-US-EmmaMultilingualNeural` | | `TAI_PASSPHRASE` | Personal seal key | Unset: built-in key; empty: plaintext | | `TELEGRAM_BOT_TOKEN`| Bot token, or set during install | Empty | ## Testing python3 test_seal.py python3 test_tai.py ## Layout tai.py the entire agent test_seal.py seal regression tests test_tai.py skills, telegram, install, and parser tests