Skip to main content

Straylight — the open-source, self-hosted gated AI agent (the gate is the only path to tools).

Project description

Straylight

Straylight is an open-source, self-hosted, gated AI agent — a general-purpose, OpenAI-compatible assistant (à la Claude Code / a Hermes agent) where the Strahl Prism information-flow gate is the only path to tools.

You prompt it; it works automatically — multi-step tool use (read files, search, run shell, edit code) to a result. The difference from any other agent: every tool call is authorized by the gate before it runs, so untrusted data (a fetched web page, a file's contents, command output) can't drive a sensitive action. Coverage is 100% by construction, and it fails closed — if the gate is unreachable, nothing runs.

Quick start

Needs two things running: an OpenAI-compatible model (a tool-capable one — e.g. Qwen2.5 via Ollama or vLLM) and a Prism gate.

uv sync

# point at your model + gate (or pass --model_url / --gate_url as flags)
export STRAYLIGHT_MODEL_URL=http://localhost:11434/v1      # Ollama's OpenAI endpoint
export STRAYLIGHT_MODEL=qwen2.5
export STRAYLIGHT_GATE_URL=http://localhost:8000
export STRAYLIGHT_API_KEY=sk_live_...                      # if your gate requires a key

uv run straylight                 # interactive REPL (bare command == `chat`)
uv run straylight run "list the python files and summarise the largest one"
uv run straylight tools           # show the toolset + which are active

In the REPL: streamed Markdown answers, each tool call and gate PERMIT / DENY shown inline. /reset starts a fresh conversation, /tools lists tools, /exit quits, Ctrl-C stops the current turn.

Models

straylight drives any OpenAI-compatible endpoint, so it works with the leading open-source models — Qwen 2.5/3, Llama 3.1/3.3, Mistral/Mixtral, DeepSeek, Hermes, and Gemma 3. straylight models lists them; the only model-specific thing that matters is the tool-call parser, which the serve scripts pick automatically. (Gemma 3 tool calling uses vLLM's pythonic parser — the serve script auto-fetches its chat template — and is less robust than Qwen/Llama; Gemma 2 has no native tool calling. Pair Gemma with STRAYLIGHT_STREAM=false if its tool calls don't stream cleanly.)

uv run straylight models                              # the supported models + how to serve each

# Easiest — Ollama (OpenAI-compatible on :11434/v1, straylight's default STRAYLIGHT_MODEL_URL):
scripts/serve-ollama.sh qwen2.5:7b                    # pulls + serves; prints the env to export

# Self-hosted — vLLM (auto-selects the tool-call parser by family):
LOCAL_LLM_PORT=8020 scripts/serve-model.sh meta-llama/Llama-3.3-70B-Instruct
export STRAYLIGHT_MODEL_URL=http://localhost:8020/v1  STRAYLIGHT_MODEL=Llama-3.3-70B-Instruct

Hosted OSS (OpenRouter / Together / Fireworks) also works — just set STRAYLIGHT_MODEL_URL + STRAYLIGHT_API_KEY to theirs. If a model's tool calls don't stream cleanly, set STRAYLIGHT_STREAM=false (a non-streaming fallback). The agent needs a tool-calling-capable model — that's the only requirement.

How it works

The loop is a generator: the model streams, proposes tool calls, the gate authorises each, permitted ones execute, and the loop repeats until the model answers.

 prompt ─► model (stream) ─► proposed tool calls ─► [ Prism gate ] ─► permitted run / denied blocked ─► loop
                                                          │
                                                    strahl SDK · POST /v0/analyses
  • agent.py — the gated loop, emitting typed events.py (streamed text, tool calls, verdicts, results) so the CLI (and, later, a serve mode) render the same core without touching loop logic.
  • tools.py — the toolset (web_fetch, read_file, list_files, glob, grep, write_file, edit_file, bash, run_python), each carrying an IFC label (requires/produces) that is the policy the gate enforces. Filesystem/shell tools are confined to a workspace; web_fetch blocks non-public hosts (SSRF guard).
  • config.py — one pydantic-settings object (env / .env / CLI flags).
  • cli.py — the Rich REPL + one-shot run.

The gate boundary — HTTP only

Straylight reaches the gate only over HTTP, through the published strahl SDK (POST /v0/analyses). It depends on the SDK for the labeled-transcript types and the gate call, and never imports the gate's decision code or the GPU attribution service — that stays behind the HTTP boundary, which is what keeps the gate tamper-proof and this subtree cleanly open-source. The agent tier holds no GPU; both GPU workloads (the model, the gate's attribution) sit behind APIs.

straylight ──strahl SDK──► analysis ──► attribution   (the Prism gate; GPU)
   └────────/v1/chat/completions──────► model          (the LLM; GPU)

Configuration

All via env (prefix STRAYLIGHT_, .env supported) or CLI flags; legacy STRAHL_* names still work.

setting env default
model endpoint STRAYLIGHT_MODEL_URL http://localhost:11434/v1
model name STRAYLIGHT_MODEL local
gate URL STRAYLIGHT_GATE_URL http://localhost:8000
gate API key STRAYLIGHT_API_KEY
workspace (tool root) STRAYLIGHT_WORKSPACE cwd
max tool steps STRAYLIGHT_MAX_STEPS 25
toolset subset STRAYLIGHT_ENABLED_TOOLSETS all (read,files,code,safe presets)

Development

uv run ruff format --check . && uv run ruff check . && uv run ty check . && uv run python -m pytest -q

Tests are hermetic — a fake gate + fake model exercise the permit/deny/fail-closed paths, the streaming parser, the toolset, and config; no network, model, or gate required. (Use python -m pytest: the bare pytest launcher misses the path-based editable strahl install.)

Design docs

The design docs live in docs/. Start with architecture — the map: the module tree, end-to-end data-flow traces, and the invariants that make straylight gated. Then the subsystems: trust-model (how provenance labels are synthesized on a bare filesystem), toolset (the tools and the policy on each), and memory (persistent, injection-safe local memory). A browsable site builds with uv run mkdocs serve (adds an auto-generated API reference from the docstrings).

Conventions

uv, Python 3.14, src/ layout, hatchling, ruff (line-length 120), pytest. Depends on strahl (the SDK).

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

straylight_agent-0.1.0.tar.gz (133.6 kB view details)

Uploaded Source

Built Distribution

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

straylight_agent-0.1.0-py3-none-any.whl (48.5 kB view details)

Uploaded Python 3

File details

Details for the file straylight_agent-0.1.0.tar.gz.

File metadata

  • Download URL: straylight_agent-0.1.0.tar.gz
  • Upload date:
  • Size: 133.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for straylight_agent-0.1.0.tar.gz
Algorithm Hash digest
SHA256 f39743c97d3ff8b668f1a40577d053a33db7981e3d4fa4201405ee713e4b9351
MD5 0256c397113f2c101b977aa85af75bec
BLAKE2b-256 aec0bf2fb137ab59f9d5c4247ee6b0f5365a52d043bbba8852841a085a1451c4

See more details on using hashes here.

Provenance

The following attestation bundles were made for straylight_agent-0.1.0.tar.gz:

Publisher: straylight-agent-publish.yml on strahl-labs/strahl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file straylight_agent-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for straylight_agent-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b4e39b32ee0ec111ff9cbc7cb353316dcc7c2321c01b6d6032569fbbb1323488
MD5 fe80685e8ee06b505589adf28c40e612
BLAKE2b-256 d1d6bfde5fff122adcd269025c46150cde10a6d5bf492e1a2cff1b5bc36a2788

See more details on using hashes here.

Provenance

The following attestation bundles were made for straylight_agent-0.1.0-py3-none-any.whl:

Publisher: straylight-agent-publish.yml on strahl-labs/strahl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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