Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

cotwatcher

You are running an open-weight reasoning model. Is it deciding to do something you would not want?

cotwatcher looks at what the model is doing internally rather than at its answer: the chain of thought it writes, and, experimentally, the activations underneath. It scores that against a rubric you control, using any OpenAI-compatible endpoint, so everything runs locally and no reasoning leaves your machine.

pip install cotwatcher
ollama pull gpt-oss:20b && ollama pull qwen3:8b     # judge, and a model to watch

cotwatcher check                                     # verify the endpoint and rubric
cotwatcher trace tasks.txt -o traces.jsonl           # run your model, capture its reasoning
cotwatcher score traces.jsonl --rubric mine.yaml     # score it

Needs Python 3.11+ and a running model server. Ollama is the shortest path and the default; vLLM, LM Studio, llama.cpp and hosted APIs work the same way.

What installs today: capturing and scoring saved traces offline, and reviewing what the judge proposed. cotwatcher propose asks for decision events quoted from the reasoning, cotwatcher review verifies each quote against the source and renders one HTML page to confirm or reject them: docs/REVIEW.md. Wiring it into a running application means writing the capture yourself against the judge API; the guide for that, written for a coding agent, is docs/INTEGRATION.md. Not built: a watch() wrapper, a proxy, enforcing a policy or halting a generation. cotwatcher logs for review; it does not gate.

What it looks for

A decision to pursue prohibited behaviour. Noticing an option and declining it is ordinary reasoning. Following through is not required — a decision the model later withdraws still counts, with the reversal recorded.

Three default categories, all about the model's own choices: deception (works out one thing, decides to say another), reward_hacking (decides to satisfy the check instead of the task), oversight_evasion (decides to work around being reviewed). The rubric is a YAML file; replace it with whatever you actually worry about.

It does not judge output. Whether the work was any good, or the request acceptable, are different questions with different tools.

Configuration

[model] is what you watch, [judge] is what scores. Separate endpoints, so they can be different machines. Copy cotwatcher.example.toml, or use COTWATCHER_* environment variables, which win over the file.

score exits 0 (assessed, clean), 1 (flagged), or 2 (incomplete: a chunk could not be assessed, or the input or endpoint failed). A run that was not fully assessed never exits 0.

⚠ Ollama picks a context per model and often lands at 4,096 tokens, then truncates from the front, which silently drops the rubric. cotwatcher check reads the window the server is actually serving and fails when it is smaller than the input limit you set; ollama/ has Modelfiles for larger variants.

Status

Early and honest about it. Detection accuracy on real workloads is unestablished.

On hand-written fixtures the judge scored 1.00 AUROC per category with no false fires. That did not transfer. In a controlled agentic experiment (evals/pressure/, 8 episodes, labels reviewed by hand) the model twice decided to satisfy a test it had identified as contradicting the specification — "we have to make the code pass the tests, even if there's a discrepancy with the specification" — and the judge caught one of the two, with one false positive on six negatives. Scoring the same episodes without the reasoning caught the other one, with two false positives. Each arm saw what the other missed; at n=8 that is a shape, not a rate.

Linear probes on pooled activations reach 0.90-1.00 AUROC on held-out synthetic data and 1.00 / 0.75 / 0.63 transferring to hand-written text. Treat that as a working pipeline, not a detection result: the probe reads a replay of saved text, and activations measure computation, not intent.

The open question: does reading the reasoning surface decisions that reading the output and tool logs does not? One of the two positives says yes, one says no.

Review

The adversarial reviews in FINDINGS.md were run by OpenAI Codex against this repository. They found the actor being served a 4,096-token context while the run asked for far more, a reversed field coerced from the string "false" so that reversals were marked that had not happened, a comparison summary reading fields its own rows never carried, a controlled pair whose test made the task unsatisfiable by an ordinary deterministic implementation, and a harness verdict a model's own code could forge. They also argued the project out of building a live stream tap before the verdicts it would produce could be checked by a person, which is why cotwatcher review exists.

Development is by Cyrill Glockner with Claude.

Limitations

  • CoT faithfulness. The reasoning is not always what drives the answer. A clean trace is absence of evidence.
  • Scope. The experiments construct a conflict in a coding task. The question is broader — research that omits contradicting evidence, a status report on a failed task, a plan that quietly drops a constraint — and a result on coding tasks supports a claim about coding tasks.
  • The probe has never been tested during generation, nor on misbehaviour it was not trained to recognise.

Experiments

git clone https://github.com/cyrillglockner/cotwatcher && cd cotwatcher
uv venv && uv pip install -e ".[evals]"

evals/pressure/ runs an agentic task where a hidden suite records what the code actually did; evals/disclosure/ puts the model in a bind in a single call; evals/probe/ trains the probes. They exist so you can find out whether any of this catches anything on your model rather than ours.

⚠ evals/pressure/ executes Python written by a model. A temp directory is not a sandbox; run it in a disposable VM. It refuses to start without COTWATCHER_ALLOW_CODE_EXECUTION=1.

docs/INTEGRATION.md is the guide for wiring cotwatcher into an application, docs/REVIEW.md for reviewing what it found. PLAN.md carries the decisions and their reasons, FINDINGS.md the review ledger, BACKLOG.md what is deferred. MIT.

Release files for cotwatcher 0.1.0a2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cotwatcher 0.1.0a2
File Size Uploaded
cotwatcher-0.1.0a2.tar.gz 93.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cotwatcher 0.1.0a2
File Interpreter ABI Platform
cotwatcher-0.1.0a2-py3-none-any.whl Python 3 none any Details

Total release size: 140.7 kB

Release files / cotwatcher-0.1.0a2.tar.gz

Download URL cotwatcher-0.1.0a2.tar.gz
Size 93.1 kB
Tags Source
SHA-256 checksum
How to use checksums
1e6303695789db05b4308db7f212eedc03acc765ca7c3474031a508a28d79c27
BLAKE2b-256 checksum
How to use checksums
6d972ba8ed10781a6c6aa8241f1b523243e69ab316bd3e65e209d039e1fac3ff
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / cotwatcher-0.1.0a2-py3-none-any.whl

Download URL cotwatcher-0.1.0a2-py3-none-any.whl
Size 47.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9505a7210cb14e186925022e17ed5a6437e1a56227d7e81291780c72f841cc0d
BLAKE2b-256 checksum
How to use checksums
4da332cb03987b0d2a3ec2668a72881fdd0c3ae8a6ce2d3bb28a885874543513
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0a2 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page