timu
timu—Swahili for team—brings together specialised LLM agents, each with a defined role that determines its prompt, tools, and permissions. Workflows coordinate these roles to achieve a shared objective.
Status: alpha. The design is in docs/dev/design.md.
Architecture
The source is docs/media/architecture.d2. make diagrams regenerates the SVG.
Roles
| Role | Can | Cannot |
|---|---|---|
lead |
read the workspace, delegate to the others | write files, run commands |
researcher |
search and fetch the web | touch the workspace |
coder |
read, write and edit files, run commands | reach the network |
reviewer |
read files, run tests, return a report | change the code |
No role holds network access together with the ability to write files or run commands. Web content, and anything derived from it, reaches other agents only as marked, untrusted data. See design section 6.
Workflows
A workflow turns one objective into tasks for agents and combines their results. It decides which roles run, in what order, and what passes between them. timu has two kinds (design section 7):
- Pipeline: Python code starts agents in a fixed order.
- Delegation: a
leadagent starts other agents with itsdelegatetool, in an order it picks at run time.
The built-in workflows, in src/timu/workflow.py:
| Workflow | Kind | Steps |
|---|---|---|
fix-review (default) |
pipeline | Coder, then reviewer. The report's first line is VERDICT: APPROVE or VERDICT: CHANGES. On CHANGES, the coder gets the report and tries again. Stops on approval or after --max-rounds (default 3). A report with no verdict fails the run. |
research-fix-review |
pipeline | Researcher first. Its findings and source URLs go to the coder as untrusted inputs. Then fix-review. |
lead |
delegation | The lead delegates to the researcher, coder and reviewer. Delegation depth is at most 2. |
All agents in a workflow share one Run: one budget, one trace, one cancel flag. Each agent gets the smaller of its role's budget and what the run has left. Agents pass work as artifacts that record their origin. They never paste it into a goal, so the untrusted mark survives.
Adding a workflow
Workflows are code. timu.toml cannot define one, and there is no plugin hook. A workflow is a function that takes a Run and an objective and returns a Result:
def code_then_review(run: Run, objective: str) -> Result:
coded = run.run_agent(CODER, Task(objective, accept="The tests pass."))
if coded.status == "done":
work = Artifact("coder-summary", coded.summary, origin=Origin.AGENT,
source=coded.trace_id, untrusted=coded.untrusted)
coded = run.run_agent(REVIEWER, Task("Review the coder's work.", (work,)))
run.emit("workflow_result", status=coded.status, summary=coded.summary)
return replace(coded, usage=run.used, trace_id=run.run_id)
To expose it, add its name to the --workflow choices in src/timu/cli.py and call it from main. main also lists the roles whose providers it checks before the run starts.
Requirements
-
Python 3.11 or later. No runtime dependencies.
-
macOS, for the
shelltool's sandbox (sandbox-exec). Elsewhere, roles that run commands refuse to start unless you pass--unsafe-no-sandbox. -
An OpenAI-compatible model API: OpenRouter by default, or a local server such as llama-server.
-
Optional: a Brave Search API key in
BRAVE_API_KEY, so the researcher can search as well as fetch.
Install
uv sync # from a checkout; `make help` lists the other targets
uv run timu --help
Configure
timu reads ~/.config/timu/timu.toml. A minimal file:
[provider]
model = "openai/gpt-6-luna" # an OpenRouter model id
# base_url = "http://127.0.0.1:8080/v1" # a local server instead
# api_key_env = "" # a server without a key
[sandbox]
extra_read = ["~/.local/share/uv/python"] # toolchains under $HOME
A ./timu.toml in the current directory overrides it, but may set only provider.model, provider.timeout, provider.extra_body and [roles]. A cloned repo can ship that file, so it cannot choose where requests and keys go or what the sandbox reads. Agents cannot write timu.toml or .timu/ in the workspace.
The API key comes from OPENROUTER_API_KEY, or the variable api_key_env names. TIMU_MODEL and TIMU_BASE_URL override the file. src/timu/config.py documents every key, including per-role models, skills and the search key.
The sandbox hides $HOME from commands. List any toolchain that lives there, such as uv's Python, in extra_read, or commands that use it fail.
Run
timu run "make test fails; fix calc.py"
timu run --workflow research-fix-review "upgrade to the current tomllib API"
timu run --workflow lead "add a --json flag to the report command"
--workflow picks one of the workflows above. The reviewer's report goes to REVIEW.md, or --report PATH. Add it to .gitignore; timu warns if it is not ignored.
Useful flags:
-
--max-cost USDstops the run at a spending limit. All agents share one budget. -
--approve-untrustedasks on the terminal before web content reaches the coder. It is on by default forlead. Without a terminal the answer is no; pass--no-approve-untrustedfor unattended runs. -
-vshows every tool result.
Exit codes: 0 approved or done, 1 failed or refused, 2 usage error, 3 budget spent, 130 interrupted. Press Ctrl-C once to stop after the current step, twice to abort.
Traces
Every run writes a JSONL trace to ~/.local/state/timu/runs/, outside the workspace.
timu trace # the latest run: agent tree, status and cost
timu trace <run id>
Develop
make qa # lint, format check, typecheck, tests
TIMU_LIVE=1 make test # also the live tests; billed against the configured model
The live tests are skipped by default. With TIMU_KEEP_TRACES=tests/fixtures/traces, the CLI live tests save their traces as replay fixtures, with local paths and your username replaced by placeholders. make test replays every fixture there.
Release files for timu 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| timu-0.2.0.tar.gz | 101.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| timu-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 161.7 kB
Release files / timu-0.2.0.tar.gz
| Download URL | timu-0.2.0.tar.gz |
|---|---|
| Size | 101.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bd64d48ce4e51634e76850d5a9482effd5224bf6f543e4e5b63b2296fd71611c
|
|
BLAKE2b-256 checksum How to use checksums |
bd05db114f07972735c9abd7938802bbad9213e4dea9c7e6a893a66951944352
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / timu-0.2.0-py3-none-any.whl
| Download URL | timu-0.2.0-py3-none-any.whl |
|---|---|
| Size | 60.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a11ea730d8fbb729f3674ac6dc592a102f09abcd577c330ef931cce0bb4ca1cc
|
|
BLAKE2b-256 checksum How to use checksums |
828b24f1e9bdd2667872c491f92de45a0b2dfd394bd4f63e8842062d95a16d11
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|