Self-learning local code agent runtime
Project description
sagex
Self-learning local code agent that watches your codebase, acts autonomously, and gets smarter with every cycle.
The agent that learns your codebase so you don't have to explain it twice.
What it does
Sagex runs alongside your project. It watches for file changes, reasons about what matters, takes action via LLM agents, and reflects on outcomes — storing lessons in a local SQLite knowledge base that improves every cycle.
File change detected
↓
Triage agent → is this worth acting on?
↓
Task agent → plan and apply edits
↓
Meta agent → what did we learn?
↓
Rules DB → store lesson for next time
Install
Python (PyPI)
pip install sagex
Node (no Python setup needed — the wrapper installs sagex into a private venv during npm install, or on first use via npx)
# Install globally so the `sagex` CLI is on your PATH:
npm i -g sagex-runtime
sagex --version
sagex serve --port 8765
# Or one-shot without installing (must repeat for every call):
npx -p sagex-runtime sagex --version
Choose a provider (v0.2.0+)
Sagex talks to four LLM providers behind the same interface. Pick one in
.agents/config.yaml under agent.provider::
| Provider | Auth | Cost | Best for |
|---|---|---|---|
anthropic_api (default) |
ANTHROPIC_API_KEY env |
Pay-per-token (Anthropic) | Teams, predictable spend |
claude_code |
Local claude login |
$0 (Claude Pro/Max subscription) | Solo devs already paying for Claude Max |
openai_api |
OPENAI_API_KEY env |
Pay-per-token (OpenAI) | OpenAI customers / GPT-5 preference |
ollama |
None | $0 (local hardware) | Privacy, offline, hobbyists |
For a one-off run without editing the config, override with
SAGEX_PROVIDER=ollama sagex serve .... See docs/PROVIDERS.md for
quality expectations, hardware guidance, and known caveats per provider.
Quick start
Follow the steps in order — skipping step 2 or 4 leaves you with a
registered-but-silent runtime that looks healthy in status but never
runs a cycle.
1. Start the runtime
# Authenticate for your chosen provider (one of):
export ANTHROPIC_API_KEY=sk-ant-... # anthropic_api (default)
export OPENAI_API_KEY=sk-... # openai_api
claude login # claude_code (npm i -g @anthropic-ai/claude-code)
# ollama needs nothing — ensure `ollama serve` is running
# In terminal 1 (leave running):
sagex serve --port 8765
2. Scaffold the project config
In your project repo (separate terminal):
sagex init .
This writes .agents/config.yaml with a placeholder name my-project
and prints next-step instructions.
3. Edit .agents/config.yaml — this is mandatory
At minimum, set:
name:— a real project name (the string you will use in every subsequent CLI command).sagex registerwill refuse to proceed while this is stillmy-project.watch.paths:— globs that match the source files you care about.test.command:— the command sagex will run before and after applying changes to detect regressions.
The file is heavily commented — read it top to bottom; every section has inline notes.
4. Install the git hooks
sagex init creates hook scripts under .agents/hooks/ but does not
install them into .git/hooks/. Without this step, commits and pushes
never fire agent cycles — you can still sagex trigger manually, but the
watchful-observer flow is inert.
ln -sf "$(pwd)/.agents/hooks/post-commit" .git/hooks/post-commit
ln -sf "$(pwd)/.agents/hooks/pre-push" .git/hooks/pre-push
5. Register with the runtime
sagex register .agents/config.yaml
# → Registered: <your-project-name>
6. Verify and exercise
Replace <your-project-name> below with the value you set in step 3:
# Does the runtime know about us?
sagex status <your-project-name>
# Fire a dry-run cycle without needing a real commit:
sagex trigger <your-project-name> --dry-run
# After a real commit has fired the post-commit hook:
sagex usage <your-project-name> --last 1h
CLI reference
sagex --help / sagex <command> --help is the authoritative source.
This table is a quick index.
Top-level
| Flag | Description |
|---|---|
--version |
Print the installed sagex version and exit. |
--help |
Print command list and exit. |
sagex init REPO_PATH
Scaffold .agents/config.yaml, .agents/.gitignore, and the hook scripts
under .agents/hooks/. Does not install the hooks into .git/hooks/
— that is a separate, manual step (see Quick Start step 4).
| Argument | Description |
|---|---|
REPO_PATH |
Path to the project repo root. Use . when run from the repo. |
sagex register CONFIG_PATH
Register a project config with a running sagex serve runtime.
| Argument / Flag | Description |
|---|---|
CONFIG_PATH |
Path to .agents/config.yaml. |
--force |
Allow registering even if name: is still the template default (my-project). Intended for tests and scripted setups. |
sagex serve
Start the agent runtime server. Long-running process; runs event handling and the FastAPI control API.
| Flag | Default | Description |
|---|---|---|
--host |
0.0.0.0 |
Interface the HTTP server binds to. 127.0.0.1 for local-only. |
--port |
8765 |
TCP port. |
--max-concurrent |
3 |
Ceiling on concurrent active agent tasks (the asyncio.Semaphore). Approval waits run outside this cap. |
sagex status PROJECT_NAME
Print rules count, today's token spend, and recent episodes.
| Argument / Flag | Default | Description |
|---|---|---|
PROJECT_NAME |
— | Must match name: in the registered config.yaml. |
--runtime-url |
http://localhost:8765 |
Override when serve runs on a non-default host/port. |
sagex usage PROJECT_NAME
Token spend and cost breakdown over a time window.
| Argument / Flag | Default | Description |
|---|---|---|
PROJECT_NAME |
— | Registered project name. |
--last |
24h |
Window. Accepts 1h, 24h, 7d. |
--runtime-url |
http://localhost:8765 |
Runtime HTTP URL. |
sagex trigger PROJECT_NAME
Manually drive one agent cycle — useful for testing without waiting for a real git commit.
| Argument / Flag | Default | Description |
|---|---|---|
PROJECT_NAME |
— | Registered project name. |
--dry-run |
off | Generate the plan without applying any file changes. |
--runtime-url |
http://localhost:8765 |
Runtime HTTP URL. |
sagex notify
Called automatically by the installed git hooks. Rarely invoked directly.
| Flag | Required | Description |
|---|---|---|
--event |
yes | Event type — commit or push. |
--repo |
yes | Absolute path to the project repo root. |
--runtime-url |
no (default http://localhost:8765) |
Runtime HTTP URL. |
Environment variables
| Variable | Required when | Description |
|---|---|---|
ANTHROPIC_API_KEY |
provider: anthropic_api |
Anthropic API key. |
OPENAI_API_KEY |
provider: openai_api |
OpenAI API key. |
SAGEX_PROVIDER |
optional | Override agent.provider in the config for this process (values: anthropic_api, claude_code, openai_api, ollama). |
AGENTIS_LOG_LEVEL |
optional | DEBUG, INFO (default), WARNING, ERROR. |
AGENTIS_DB_PATH |
optional | Override the default global usage DB location (~/.agentis/usage.db). |
For local development, drop these into a .env file at the repo root —
sagex serve loads .env via python-dotenv on startup. .env is
gitignored by default.
What triggers an agent cycle
Four paths — in decreasing order of "actually what you want in daily use":
- Post-commit hook — every
git commitfiressagex notify --event=commit --repo=<pwd>, which enqueues an event. Requires the symlink from Quick Start step 4. - Pre-push hook — same as above but on
git push. - Manual
sagex trigger <project>— best for testing. Works even without hooks installed. - Direct HTTP POST to
/notifyon the runtime. Used by CI systems and custom integrations.
If you install the hooks but still see Total events: 0 after a commit,
check that sagex serve is running on the same URL the hooks point at
(default http://localhost:8765).
Configuration (.agents/config.yaml)
sagex init . creates .agents/config.yaml in your project. The YAML
below is an illustrative excerpt of the default config — the
authoritative source is src/sagex/cli.py::_CONFIG_TEMPLATE, which is
what sagex init actually writes (with additional knowledge:,
runner:, and notifications: sections and slightly different
formatting). One agent: block drives all four sub-agents (triage,
task, meta, security); per-agent token ceilings live on the same block.
name: my-project # CHANGE ME — `sagex register` refuses the template default
repo_root: .
watch:
paths:
- "src/**/*.py"
- "tests/**/*.py"
- "*.yaml"
- "*.toml"
ignore:
- "**/__pycache__/**"
- "**/.git/**"
- "**/*.log"
debounce_seconds: 2.0
test:
command: "pytest tests/ -x --tb=short"
timeout_seconds: 120
agent:
# Provider selection — override per-run with SAGEX_PROVIDER=<name>
provider: "anthropic_api" # anthropic_api | claude_code | openai_api | ollama
# Leave empty to auto-resolve to the provider's default
# (anthropic_api/claude_code → claude-sonnet-4-6 + claude-haiku-4-5;
# openai_api → gpt-5 + gpt-4o-mini;
# ollama → llama3.1:8b + llama3.2:1b).
model: ""
triage_model: ""
max_tokens: 2048 # task agent output ceiling
triage_max_tokens: 512 # haiku triage classification
meta_max_tokens: 1024 # reflection JSON
security_max_tokens: 1024 # security audit JSON
summariser_max_tokens: 512 # diff pre-summariser (haiku)
temperature: 0.2
# triage_temperature: 0.0 # supported but not written by default; add if you want to override
ollama_base_url: "http://localhost:11434" # ollama only
budget:
hourly_token_limit: 50000
daily_token_limit: 500000
alert_threshold: 0.8
content_cache_ttl_minutes: 60
enable_prompt_caching: true # Anthropic cache_control, threshold-guarded
agents:
security:
enabled: false
watch_extra:
- ".env*"
- "**/*secret*"
- "**/requirements*.txt"
- "**/Dockerfile*"
auto_remediate: false
Cross-provider model settings (e.g. provider: openai_api +
model: claude-sonnet-4-6) fail at config-load with a clear error.
Troubleshooting
sagex status <name> returns zeros for everything.
Either no events have fired yet, or you registered under a different
name. Run curl -s http://localhost:8765/projects — if your project
isn't listed, sagex register .agents/config.yaml again.
Connection refused from sagex register or sagex status.
sagex serve isn't running, or it's on a different port. Check with
curl -s http://localhost:8765/projects — if that errors too, the
runtime is down.
Commits happen but Total events stays at 0.
The git hooks weren't installed. Rerun Quick Start step 4. Confirm with
ls -la .git/hooks/post-commit — it must be a symlink into .agents/.
register exits with "template default" error.
Expected — edit name: in .agents/config.yaml to a real project name
before running register. See Quick Start step 3.
Requirements
- Python 3.11+
- One provider's auth, depending on your
agent.providerchoice:anthropic_api—ANTHROPIC_API_KEYenv varclaude_code— localclaudeCLI (npm i -g @anthropic-ai/claude-code) +claude loginopenai_api—OPENAI_API_KEYenv varollama— nothing;ollama serverunning locally
- SQLite (bundled with Python)
Publishing
See PUBLISHING.md for instructions on releasing to PyPI and npm.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sagex-0.2.4.tar.gz.
File metadata
- Download URL: sagex-0.2.4.tar.gz
- Upload date:
- Size: 152.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
27f5f97faa28738eede340c377fe14002d13e2f23da7ca5398b2169d8df2ee50
|
|
| MD5 |
adfb2d476223b8106ada0ba18eed6b0c
|
|
| BLAKE2b-256 |
6a8d29523125c945944c74eb30adb6e6fd5f586bb461088c9d3acb1347039794
|
File details
Details for the file sagex-0.2.4-py3-none-any.whl.
File metadata
- Download URL: sagex-0.2.4-py3-none-any.whl
- Upload date:
- Size: 98.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
547e13a04107addfacbae71eac1cebf4486f0a1c8c161f953f4936ea8a92fda5
|
|
| MD5 |
42f078f4736795acde6906ad100fe2c4
|
|
| BLAKE2b-256 |
e936a8690b14d68474af67b068c144817a878dba6f7287ae6b8804dc04a2be1e
|