Skip to main content

Reflexes — open standard for AI agent policy checks.

Project description

Reflexes

Reflexes is an open safety harness for AI agents. At inference-time it checks each agentic decision point against plain-English policies to keep agents on track. It is an open standard and ships with this reference implementation.

License

Status: v0.1 — first public release. Claude Code, OpenAI Codex, LangGraph, and Google ADK are Stable; other hosts are Beta or Experimental — see FRAMEWORKS.md for per-host maturity.

Contents

Getting started

Using Reflexes

Reference

How it works

AI agents drift: they run a destructive command, overstep the instructions you gave, assert something they never verified, or stop before the job is done — and you often find out only after the tool has run or the reply has shipped. Reflexes is the safety net. You write the rules in plain English, and it checks the agent against them at each decision point, catching a mistake before it lands and handing the agent the rule so it can correct itself — no babysitting required.

Reflexes has five key components, wired together in a reflexes.yaml file:

  • Policy — a rule written in plain English as a markdown file (e.g. "don't delete data without confirmation"). The whole document is the criteria.
  • Triggerwhen a policy is checked: on_input (a user message), before_tool_call, after_tool_call, or before_response.
  • Actionwhat happens on a match: deny (block, and hand the policy text back so the agent self-corrects), flag (allow but record it), or log.
  • Binding — a line in reflexes.yaml tying a policy to a trigger and an action. Your bindings are your configuration.
  • Evaluator — the classifier that decides whether content matches a policy. The default is CoPE, a small model purpose-built for it; you can also use OpenAI, Anthropic, or Gemini.

At each trigger, Reflexes asks the evaluator whether the content matches each bound policy, and on a match takes the action — usually deny, which feeds the policy back so the agent corrects its own course.

By telling an agent which policy it broke and why, Reflexes help agents revise and adapt, instead of just looping against a wall or breaking one of your rules.

Quick Install — via Agents

Reflexes can install itself. Just tell your coding agent to install the Reflexes skill:

Install the reflexes skill from github.com/zentropi-ai/reflexes then wire it into this agent.

Your agent reads SKILL.md and does the rest for your host (Claude Code, OpenAI Codex, Hermes, or OpenClaw): detects the host, installs the starter policies, writes ~/.reflexes/reflexes.yaml, and wires the hooks without disturbing your existing config — then verifies with reflexes doctor. It's idempotent, so you can re-run it any time.

Prerequisites: Python 3.10+, uv, and — for the default CoPE evaluator — a free ZENTROPI_API_KEY from zentropi.ai.

Building an agent in code with a Python framework (OpenAI Agents SDK, LangGraph, Google ADK, …) rather than a host CLI? pip install reflexes and wire it in — see Quick Install — via Python Frameworks.

Quick Install — via Python Frameworks

First, install the package:

pip install reflexes
# the OpenAI Agents SDK integration also needs the `openai` extra:
pip install "reflexes[openai]"

For OpenAI Agents SDK and Google ADK:

from reflexes import with_reflexes

agent = ...  # your framework's agent object
agent = with_reflexes(agent, reflexes=["default"], config_file="reflexes.yaml")

For LangGraph:

from langchain.agents import create_agent
from reflexes import middleware_from_config

agent = create_agent(
    model=...,
    tools=[...],
    middleware=[middleware_from_config(reflexes=["default"], config_file="reflexes.yaml")],
)

For Claude Agent SDK (use create_hooks(), not with_reflexes()):

from claude_agent_sdk import ClaudeAgentOptions, query
from reflexes.integrations.claude_agent_sdk import create_hooks

options = ClaudeAgentOptions(
    hooks=create_hooks(reflexes=["default"], config_file="reflexes.yaml"),
)

What you get out of the box

The install ships six starter policies, ready to use, in two groups:

  • Integrity (enabled by default):
    • Unconfirmed-Destructive-Action — don't delete or destroy data without confirmation.
    • Constraint-Violation — don't overstep the user's stated instructions.
    • Sycophancy — give honest judgment, not flattery.
  • Autonomy (installed, off by default — uncomment in reflexes.yaml to enable): Early-Stopping, Laziness-Detection, Unsourced-Claims — help a long-running agent actually finish the job and ground its claims.

Where to go next:

  • Pick your policies — edit ~/.reflexes/reflexes.yaml to enable/disable policies or change an action (e.g. denyflag). See Configuration.
  • Write your own — drop a markdown policy in ~/.reflexes/policies/ and bind it. See Writing a policy.
  • Swap the evaluator — use OpenAI / Anthropic / Gemini, or self-host CoPE. See Evaluators.

Configuration

reflexes.yaml is the single source of truth for which policies fire where. Here is an example:

reflexes:
  default:
    - policy: ./policies/Unconfirmed-Destructive-Action.md
      name: Unconfirmed-Destructive-Action
      trigger: before_tool_call
      action: deny
    - policy: ./policies/Sycophancy.md
      name: Sycophancy
      trigger: before_response
      action: deny

evaluators:
  default:
    type: zentropi
    model: cope-latest
    api_key_env: ZENTROPI_API_KEY

# --- Operational settings (optional; safe defaults) ---
enabled: true      # global on/off; false disables ALL enforcement. Absent = enabled.
logging:
  level: warning   # off | error | warning (default) | info | debug — content ONLY ever at debug
  format: text     # text | json

The default group always applies. Add named groups (e.g. customer-comms, code-safety) for opt-in policy sets:

agent = with_reflexes(agent, reflexes=["customer-comms", "code-safety"])

Same (policy, trigger) pair across groups uses last-writer-wins.

Policy sources. Each binding needs a name and a policy reference. The policy can point at three kinds of source:

  • A local file (default)./policies/<name>.md. Self-contained and offline;
  • A Zentropi-hosted labelerzentropi:<labeler_id>[@<version>]. Useful when you author and version policies in Zentropi and share them across agents.
  • A GitHub-hosted filegithub:<owner>/<repo>/<path>@<tag-or-sha>. For teams that version policies in git.

Hosted policies are fetched and cached on first use, so they work with any evaluator. Pin a version for reproducible enforcement; an unpinned reference tracks the latest deployed version (Zentropi) or the default branch (GitHub).

Writing a policy

A policy is a plain markdown file, and the whole document is the criteria sent to the evaluator. CoPE is tuned for the structure the starter policies follow:

  • ## Overview — one paragraph: summary of what to detect, and the correction the agent might make when it fires.
  • ## Definition of Terms — define each load-bearing term (in bold) once.
  • ## Interpretation of Language — how to scope the check and what tips an edge case one way or the other.
  • ## Definition of Labels — the label as ### (XX): <Name> (a short code), split into #### Includes (categories that match) and #### Excludes (near-misses that must not). That Includes/Excludes boundary is what makes CoPE precise.

Generally, you do not need to write a policy on your own. Use the Reflexes Skill within your Agent to generate a conforming policy for whatever rule you want to build. Here is an example of a simple one:

# Criteria

## Overview

Fires when a tool call would permanently destroy local data (files, git history,
database records) without the user having confirmed that specific action. On a
match, the agent should say what would be lost and ask before proceeding.

## Definition of Labels

### (UDA): Unconfirmed Destructive Action

#### Includes

- **Unconfirmed deletion**: deletes or wipes data (`rm -rf`, `git clean -fd`)
  with no confirmation in the task context.
- **Irreversible history/DB change**: `git reset --hard`, `DROP TABLE`, or a
  force-push, without confirmation.

#### Excludes

- **User-requested**: the request explicitly asked for this exact destruction.
- **Reversible or regenerable**: moves to backup/trash, `git stash`, or deletes
  only rebuildable artifacts (`node_modules`, `dist/`).

See writing-policies.md for the full method and worked examples, and SPEC.md §3 for the format spec.

Triggers and actions

Trigger Fires when Content sent to evaluator
on_input The agent receives a user input The user input
before_tool_call The agent is about to invoke a tool tool_name(args)
after_tool_call A tool returned a result tool_name returned: <result>
before_response The agent is about to emit a final response The response text
Action Behavior on label=1
deny Block the operation. Surface the policy criteria text to the agent so it can self-correct.
flag Allow the operation. Make the verdict observable (logs, structured metadata, framework-native state).
log Allow the operation. Record the verdict in the diagnostic log (visible at the default level).

See SPEC.md §5–§7 for normative semantics.

Supported frameworks

Each host's maturity tier below summarizes how thoroughly the integration is validated. This is an abridged table of the most-used hosts; see FRAMEWORKS.md for the full host list (including PydanticAI, smolagents, AutoGen, and NeMo Guardrails) and the per-host evidence — live-runtime tests, dogfood passes, and known framework limits.

Framework Wiring Maturity
LangGraph middleware_from_config() 🟢 Stable
Claude Code SKILL.md agent-driven install (settings.json) 🟢 Stable
OpenAI Codex SKILL.md agent-driven install (hooks.json) 🟢 Stable
NousResearch Hermes (≥0.18) hooks: in ~/.hermes/config.yamlnous_hermes_shell 🟡 Beta — before_tool_call blocks; on_input/after_tool_call/coding-turn limits
OpenClaw @zentropi/reflexes-openclaw plugin (before_tool_call + before_response) 🟡 Beta
Google ADK with_reflexes() (callbacks) 🟢 Stable
Claude Agent SDK create_hooks() 🟡 Beta
OpenAI Agents SDK with_reflexes() + run_with_reflexes() 🟡 Beta

Evaluators

The default evaluator model is Zentropi CoPE (sub-second latency with generous free tier) — purpose-built for policy-steerable classification. It requires a free API key: create an account at https://zentropi.ai, mint a key, and set ZENTROPI_API_KEY in the environment your agent runs in.

  • Free tier — a free key covers the starter policies, your own custom policies, and everyday use.
  • Subscriber tier — high-volume usage and higher rate limits.

Privacy: the Zentropi API retains zero content by default — the policy and content you send for evaluation are not stored.

Prefer not to use Zentropi? Point Reflexes at any OpenAI-compatible model instead (see below) — no Zentropi key required.

Other evaluators are supported out of the box:

  • type: openai — any OpenAI-compatible endpoint (GPT-4o-mini, Groq, etc.)
  • type: anthropic — Claude as evaluator
  • type: gemini — Gemini as evaluator

The openai evaluator includes local deployments. Anything that exposes the OpenAI chat-completions shape on a localhost port works — Ollama (http://localhost:11434/v1), LM Studio, vLLM, llama.cpp, TGI, or your own serving stack. No api_key field needed for local servers that don't require auth. Example pointing at Ollama running llama3.1:

evaluators:
  default:
    type: openai
    endpoint: http://localhost:11434/v1/chat/completions
    model: llama3.1

When the evaluator is unreachable (network outage, rate limit), Reflexes fails open: the verdict is treated as "not available," no action fires, the agent keeps running. A governance tool that blocks production on evaluator outage won't be adopted. See SPEC.md §4.3.

Self-host CoPE (advanced)

For security-sensitive deployments or zero-API-dependency setups, CoPE runs on consumer-grade GPU hardware and can be self-hosted:

  • Weights: zentropi-ai/cope-b-a4b on Hugging Face (gated access — accept the terms; sign in once).
  • License: apache-2.0 — a true open weight model.
  • Hardware: single consumer-grade GPU is sufficient for CoPE-B-A4B. Typically sub-100ms inference latency in production deployments.
  • Token limit: 256K combined policy + content per evaluation.

Self-hosting gets you: lower per-check cost, no external API dependency, end-to-end open-source inference (open SDK + open policies + open weights). Useful where data residency or air-gapped operation is required.

Point Reflexes at your local CoPE endpoint via the OpenAI-compatible evaluator config:

evaluators:
  default:
    type: openai
    endpoint: http://localhost:8000/v1/chat/completions
    model: cope-latest

Roadmap (not yet shipped): Ollama and llama.cpp builds. Until then, run CoPE via vLLM, TGI, or your preferred OpenAI-compatible serving stack.

Observability

Reflexes ships optional OpenTelemetry instrumentation for production deployments. Install the [otel] extra:

pip install 'reflexes[otel]'

Without the extra, every observability call is a no-op — zero runtime cost. With it, each policy evaluation emits three signals to whatever OTLP backend you've configured (Datadog, Honeycomb, Grafana/Loki, …):

  • a span per evaluation, tagged with the policy, evaluator, trigger, and verdict;
  • a verdict counter, labeled by the action taken (deny / flag / log / error / no_match) — rate-limit and auth failures are counted separately from evaluator errors, so dashboards can split product signal from infra noise;
  • a latency histogram per evaluation.

For log-based stacks without OTLP ingest, set logging.format: json in reflexes.yaml to emit structured JSON logs (and logging.level to control verbosity — see Configuration). The full instrumentation surface (for custom collectors) lives in reflexes.observability.

Documentation

  • SPEC.md — the open standard (policy format, evaluator interface, trigger taxonomy, action taxonomy, self-correction protocol)
  • FRAMEWORKS.md — per-host compatibility, maturity tiers, and validation evidence
  • CONTRIBUTING.md — dev setup, how to add a framework integration or a policy, and the PR checklist
  • SECURITY.md — how to report a vulnerability privately
  • tests/ — the integration + end-to-end suite (in the source repo; not shipped in install bundles).

Contributing

Contributions are welcome under Apache-2.0. Start with CONTRIBUTING.md — it covers dev setup, adding a framework integration (add-framework-integration.md), contributing a policy (writing-policies.md), and the PR checklist. For security issues, follow SECURITY.md — please don't open a public issue for vulnerabilities.

Reflexes is stewarded by Zentropi.

License

Reflexes is licensed under the Apache License 2.0.

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

reflexes-0.1.1.tar.gz (659.6 kB view details)

Uploaded Source

Built Distribution

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

reflexes-0.1.1-py3-none-any.whl (136.5 kB view details)

Uploaded Python 3

File details

Details for the file reflexes-0.1.1.tar.gz.

File metadata

  • Download URL: reflexes-0.1.1.tar.gz
  • Upload date:
  • Size: 659.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for reflexes-0.1.1.tar.gz
Algorithm Hash digest
SHA256 48e7d2c3dbc1950496168b8c55aa19b659090b4f27bbedb2eb94a755526e2a70
MD5 d550944c2487500aad829b5ea3df4882
BLAKE2b-256 5e911a36f9f4649c5742ac6f44211493b2ad45b3ae7806ca4a8ca93708dbd306

See more details on using hashes here.

File details

Details for the file reflexes-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: reflexes-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 136.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for reflexes-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 980cfc57bdcae54f4905cea3f94f7522977a6e1cb26ac81b2a0ceb35906a5202
MD5 f7f4ac2f4d8cba9b6b4e89c949a05dbe
BLAKE2b-256 56d19db7ac56b37eab9526fbad31ae01697e11c17d9114979a0267c0d4f60bbc

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