Skip to main content

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.yamlthis is mandatory

At minimum, set:

  • name: — a real project name (the string you will use in every subsequent CLI command). sagex register will refuse to proceed while this is still my-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":

  1. Post-commit hook — every git commit fires sagex notify --event=commit --repo=<pwd>, which enqueues an event. Requires the symlink from Quick Start step 4.
  2. Pre-push hook — same as above but on git push.
  3. Manual sagex trigger <project> — best for testing. Works even without hooks installed.
  4. Direct HTTP POST to /notify on 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.provider choice:
    • anthropic_apiANTHROPIC_API_KEY env var
    • claude_code — local claude CLI (npm i -g @anthropic-ai/claude-code) + claude login
    • openai_apiOPENAI_API_KEY env var
    • ollama — nothing; ollama serve running locally
  • SQLite (bundled with Python)

Publishing

See PUBLISHING.md for instructions on releasing to PyPI and npm.


License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sagex-0.2.4.tar.gz (152.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sagex-0.2.4-py3-none-any.whl (98.5 kB view details)

Uploaded Python 3

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

Hashes for sagex-0.2.4.tar.gz
Algorithm Hash digest
SHA256 27f5f97faa28738eede340c377fe14002d13e2f23da7ca5398b2169d8df2ee50
MD5 adfb2d476223b8106ada0ba18eed6b0c
BLAKE2b-256 6a8d29523125c945944c74eb30adb6e6fd5f586bb461088c9d3acb1347039794

See more details on using hashes here.

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

Hashes for sagex-0.2.4-py3-none-any.whl
Algorithm Hash digest
SHA256 547e13a04107addfacbae71eac1cebf4486f0a1c8c161f953f4936ea8a92fda5
MD5 42f078f4736795acde6906ad100fe2c4
BLAKE2b-256 e936a8690b14d68474af67b068c144817a878dba6f7287ae6b8804dc04a2be1e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page