# AGENTS.md ## Conventions - Use plain `import` and `from` statements in Python files. - Use the `.py` extension for Python source and test files. - `tai.py` is the entire product in one standalone stdlib-only file: CLI entry plus the stable `import tai` surface, grouped into classes (instance classes for stateful clusters, static utility classes for stateless groups). It must import nothing outside the standard library; a bare copy of the file has to import and run anywhere. Canonical patch targets are `tai..` (or the module attribute for module-level data). - There are two kinds of test, in two different places, on purpose — see "Testing" below for the full split. In short: unit tests are top-level `test_*.py`; integration tests are `tests/.py` (no `test_` prefix) built on `tai_test.py`. - The in-`tai.py` TUI framework is documented in [tui.md](tui.md) — read it before touching any `Tui*` code. - The terminal multiplexer (`Mplex*` classes, `tai.py --mplex`, `~/.tai/mplex.toml`) is specified in [mplex.md](mplex.md): read it before touching any `Mplex*` code, and keep its option, command and key tables in step with the code (`MplexSpecTests` fails when they drift). ## Testing **Unit tests**: `test_tai.py`, `test_seal.py`, at the repository top level, named `test_*.py`, `unittest`-based, import `tai.py` as a module directly, no subprocess, fast. `python3 test_tai.py` / `python3 test_seal.py`, or a single test via `python3 -m unittest test_tai.SomeClass.test_method`. **Integration tests**: `tests/.py` (e.g. `tests/rag.py`), deliberately *not* named `test_*.py` and *not* at the top level, so the two kinds are never confused. These drive the real `tai.py` binary as a subprocess (one-shot or REPL) and check actual CLI behavior, using `tai_test.py` (the framework, at the repository root) as the one and only base to build on — never a one-off `subprocess`/`asyncio` harness per file. **They must exercise a real LLM call through the real binary — never a mocked model or a database write standing in for what the agent would have done; the resulting flakiness from a free, rotating backend is accepted, not engineered away.** Full conventions, that rule's full rationale, the required isolation rule (always a throwaway `TAI_HOME`), and why verification must check vault state rather than scrape CLI rendering, are in [tests/README.md](tests/README.md) — read it before adding a new one. Run with `python3 tests/.py` (`--filter`, `--interactive`, `--timeout` all supported). ## Agent Overview - `tai`: The main autonomous agent. - `devops`: A bot that manages the DevPlace DevOps platform. ## Agent Profiles - `default`: Default agent profile for general tasks. - `work`: Work-focused agent profile. - `dev`: Development-focused agent profile. ## Bot Details - `devops`: A bot that automates DevPlace DevOps operations. - Manages workspaces, projects, and deployments. - Handles user authentication and access control. - Provides development tools and utilities. - Integrates with OpenShift Dev Spaces. ## Key Features - Autonomous decision making - Multi-profile support - Background subagent orchestration - Secure vault storage - Container sandbox support - Progress tracking - Interactive REPL - Command-line interface ## Usage Examples 1. Start the main agent: ```bash ./tai.py ``` 2. Use a specific profile: ```bash ./tai.py --profile work ``` 3. Run a one-shot command: ```bash ./tai.py what is 2+3, use the shell ``` 4. Check agent status: ```bash ./tai.py --version ``` 5. Install the agent: ```bash ./tai.py --install ``` ## Development Guidelines - Write clear, concise code - Follow Python conventions - Test thoroughly - Use the agent for documentation - Keep code maintainable - Document decisions - Version control changes - Collaborate effectively ## Command Output Rule Every command an agent runs for the user (shell, ssh, sandbox box) **must stream live to the user in both modes**, in addition to being returned to the agent. It is a message, not a blocking spinner: a fixed-height window (REPL `LiveStream`, chat TUI `live` block) that keeps scrolling its last lines in place while the user keeps chatting. If the command stops on a prompt (sudo, ssh, y/n), it runs on a pty and asks the user through the same channel as `ask_user` (`agent.prompter` / REPL `input`); the answer is typed into the command, a decline sends end-of-file, and waiting for the user never counts against the timeout. Any new tool that runs a process must go through `run_live` with `Tools.shell_stream` and `Tools.shell_ask`, never a bare `subprocess.run`. Details: [tui.md](tui.md) (chat scene). ## Research Rule All external research conducted for this project (web searches, reading documentation to settle a design question, competitive/prior-art analysis) is archived under `research/`, maintained under the auspices of the **Molodetz Institute — Research & Retrieval Division**. The full specification — folder layout, the three required document types (Source Dossier, Source Citation Card, Conclusion Document), required metadata, and the quality bar — lives in [research/README.md](research/README.md); [research/INDEX.md](research/INDEX.md) is the living registry and statistics page. Read [research/README.md](research/README.md) in full before writing into this archive. The binding rule, in short: **a research task is not done until it is written into `research/`.** Every source actually consulted gets its own document (Tier 1 if read and synthesized, Tier 2 if only seen in a result listing — never skipped, never inflated past what's actually known), every decision the research produced gets its own Conclusion document in that subject's `conclusions/` folder, and `research/INDEX.md` gets updated in the same pass. Check `research/INDEX.md` for an existing subject before opening a new one.