Tiri is a local-first agent product shell built on the standalone
agent-runtime core. It packages the runtime into a practical personal-agent
experience: CLI chat, FastAPI APIs, a Next.js web shell, sandbox tools,
channel integrations, local skills, and SQLite persistence.
- Local-first backend with durable SQLite sessions, settings, channel state, event streams, and outbox records.
- Runtime composition around
agent-runtime, keeping product policy here and neutral agent mechanics in the sibling core package. - CLI and web entry points through the same
TiriBackendconfiguration path. - Local and Docker-backed sandbox tools for file access and shell execution.
- Prompt assembly from base identity, runtime environment, optional profile context, and local skill registry.
- Channel adapters for Telegram, Weixin/WeChat, and Feishu/Lark, including inbound listeners and proactive outbound messaging.
| Path | Purpose |
|---|---|
agent/ |
TiriBackend, backend config, logging hooks, and collaboration modes. |
prompts/ |
Base prompt, profile prompt, environment prompt, and skill index assembly. |
tools/ |
Tool registry composition and concrete Tiri tool sets. |
sandbox/ |
Local and Docker sandbox implementations exposed as runtime tools. |
channels/ |
Provider adapters, listeners, gateway, targets, settings, and outbox worker. |
server/ |
FastAPI app, SQLite storage, event queues, and local server runner. |
cli/ |
Thin tiri command entrypoint. |
web/ |
Next.js web shell for Tiri-specific backend integration. |
Top-level backend.py, config.py, and collaboration.py are compatibility
re-export modules. New implementation should live under the structured
packages above.
Install the sibling runtime and this product repo into a local virtual environment:
uv venv --python 3.11 .venv
uv pip install -e ../agent-runtime -e ".[server]" --python .venv/bin/python
uv pip install pytest --python .venv/bin/pythonConfigure a model:
export TIRI_LLM_API=openai-chat-completions
export TIRI_MODEL=your-model-name
export TIRI_LLM_API_KEY=your-api-key
export TIRI_LLM_BASE_URL=https://api.openai.com/v1Run CLI chat:
.venv/bin/tiriStart the local API and web shell:
.venv/bin/tiri server startThe server command starts:
- FastAPI at
http://127.0.0.1:8000 - Next.js at
http://127.0.0.1:3000
To run only the FastAPI backend:
.venv/bin/tiri server start --no-web| Variable | Purpose |
|---|---|
TIRI_LLM_API |
Provider API shape, such as openai-chat-completions. |
TIRI_MODEL |
Model name. Required unless passed with --model. |
TIRI_LLM_API_KEY |
Provider API key. |
TIRI_LLM_BASE_URL |
Optional provider base URL. |
TIRI_PROMPT_PATH |
Optional file overriding the base system prompt. |
TIRI_PROFILE_PATH |
Optional local user/profile prompt file. |
TIRI_SKILLS_PATH |
Optional local skills directory. |
TIRI_DATA_DIR |
Local data directory, defaulting to ~/.tiri when configured. |
TIRI_DB_PATH |
Explicit SQLite database path. |
TIRI_COLLABORATION_MODE |
Collaboration mode, currently default or plan. |
CLI flags mirror the most common settings:
.venv/bin/tiri --model your-model --data-dir /path/to/tiri-data
.venv/bin/tiri server start --db-path /path/to/tiri.sqliteTiri builds the system prompt from:
prompts/base.pyfor the base identity, operating loop, tool rules, workspace rules, safety guidance, and voice.- The runtime environment, such as
cli,web, orchannel:<provider>. - Optional profile context from
TIRI_PROFILE_PATH. - Optional skill registry context from
TIRI_SKILLS_PATH.
If TIRI_SKILLS_PATH is unset, it defaults to ~/.tiri/skills when
TIRI_DATA_DIR is configured, otherwise ./skills.
Enable local workspace tools:
export TIRI_SANDBOX_ROOT=/path/to/workspace
export TIRI_SANDBOX_BACKEND=localUse Docker-backed shell execution while keeping the same mounted workspace:
export TIRI_SANDBOX_BACKEND=local-docker
export TIRI_SANDBOX_DOCKER_IMAGE=python:3.12-slimThe Docker backend keeps one container per Tiri session. The container name is
derived from the session id, mounted workspace, and image, so resumed sessions
reuse their sandbox container and later run_shell calls execute through
docker exec.
Sandbox tools currently include read_file, write_file, list_files, and
run_shell.
Tiri stores local backend data in SQLite. By default, the durable database is:
~/.tiri/tiri.db
The database stores chat sessions, message history, event-stream records, local settings, channel settings, proactive targets, and channel outbox entries.
Supported local channel providers:
- Telegram long polling via the Bot API.
- Weixin polling via the ilink bot API.
- Feishu/Lark websocket via
lark-oapi.
Inbound channel events are routed through:
POST /api/channels/inbound
When exposed beyond localhost, set an inbound token and send it as
Authorization: Bearer ... or X-Tiri-Channel-Token:
export TIRI_CHANNEL_INBOUND_TOKEN=local-secretBackground channel services are enabled by default and can be disabled with:
export TIRI_CHANNEL_GATEWAY_ENABLED=false
export TIRI_CHANNEL_OUTBOX_ENABLED=falseRun Python tests:
.venv/bin/python -m pytest tests -qRun frontend checks:
cd web
npm run lint
npm run buildTiri Agent is licensed under the GNU Affero General Public License, version 3 only. See LICENSE for details.