Skip to main content

CrewAI Task guardrail blocking verification claims without evidence — empirical F1 0.815 on MAST mode 3.3

Project description

crewai-no-vibes

CrewAI Task guardrail blocking verification claims without evidence. Pure-Python, zero runtime dependencies, drop-in.

Catches the canonical agent failure: tasks closing out with "done", "verified", "fixed", "shipped", "no issues" when no actual evidence (commands run, test output, files inspected) is present.

Empirical baseline

no-vibes is the strongest measured detector for MAST mode 3.3 ("No or Incorrect Verification") — the highest-prevalence multi-agent failure mode in the canonical taxonomy.

Dataset n F1 95% CI Precision Recall
MAD human-labelled 19 0.815 [0.615, 0.941] 0.733 0.917
MAD LLM-judge full 954 0.308 [0.264, 0.352] 0.226 0.486

Inter-annotator Fleiss κ for mode 3.3 on the released human-labelled set: 1.000 (perfect agreement). Bootstrap: percentile method, B=10000 resamples, seed=42.

Full empirical report with methodology, per-MAS-framework breakdown, and limitations: https://github.com/waitdeadai/llm-dark-patterns/blob/main/evaluation/MAST-RESULTS.md

Install

pip install crewai-no-vibes

Or directly from this repository:

pip install git+https://github.com/waitdeadai/crewai-no-vibes.git

Pure Python, supports 3.9+, no external binary required. CrewAI itself is an optional dependency — the guardrail function works without it, you just won't have anywhere useful to attach it.

Usage

from crewai import Agent, Task
from crewai_no_vibes import verification_claim_evidence_guardrail

researcher = Agent(role="Researcher", goal="...", backstory="...")

task = Task(
    description="Run the benchmark and report results.",
    expected_output="A summary with command output and verification status.",
    agent=researcher,
    guardrail=verification_claim_evidence_guardrail,
)

When the agent's output claims completion without evidence, the guardrail returns (False, feedback) and CrewAI retries the task with the feedback as context. CrewAI's max_retries (default 3) caps the retry loop.

What it catches

The guardrail blocks outputs that trigger done_without_evidence:

claims_completion AND (NOT has_evidence_marker OR completion_with_negative_evidence)

Where:

  • claims_completion: message contains any of done, complete, completed, ready, implemented, fixed, resolved, verified, deployed, shipped, all set, no issues
  • has_evidence_marker: message contains command evidence (e.g. pytest, cargo test, commands run: ...) OR verification-pass evidence (verification: passed, tests passed) OR read-only-audit evidence (files inspected:, sources reviewed:)
  • completion_with_negative_evidence: completion claim PLUS a negative evidence marker (verification: not run, unverified, tests not run, could not verify) — i.e. "I'm done" while explicitly admitting verification didn't happen

Catches

"Done. All set." → BLOCKED
"Fixed. No issues found." → BLOCKED
"Implemented and ready, with no observable command or file evidence." → BLOCKED
"All tests passed, verified. (Tests not run.)" → BLOCKED  # negative-evidence override

Passes

"Implemented. Commands run: `pytest tests/` → 8 passed. Verification: passed." → OK
"Read-only audit complete. Files inspected: src/parser.py, tests/test_parser.py. No changes." → OK
"Status: partial. The scaffolding is drafted. Verification: not run because no fixture exists yet. Next step: write fixture." → OK  # honest partial with no completion claim
"Reviewing the design — no decision yet." → OK

Configuration

The default guardrail uses the upstream rule pack's settings. For customization, use the factory:

from crewai_no_vibes import make_guardrail

# Custom feedback message
guardrail = make_guardrail(
    custom_feedback="Show test output, please."
)

# Stricter mode: block on ANY completion claim without command/verification evidence,
# regardless of whether a negative-evidence marker is present.
strict_guardrail = make_guardrail(require_command_or_verification=True)

Source ledger

This package is a pure-Python port of the evidence_claims rule pack from agent-closeout-bench, the Rust YAML rule pack engine maintained alongside llm-dark-patterns.

If the upstream rule pack updates, this package version-pins to its own snapshot. Re-port for new versions; do not assume drift-free behavior.

Honest limitations

  1. Cross-surface caveat (inherited from MAST-EVAL): the underlying detector was tuned for Claude Code closeout text. MAD is multi-agent trajectory text. The F1 0.815 number is cross-surface transfer agreement with the MAD LLM-as-judge overseer, not in-surface gold-label accuracy on CrewAI-specific output text. CrewAI users may see different effective precision/recall depending on their agent's output style.
  2. Pure-Python port may diverge from Rust engine on edge cases: regex flavor (Rust regex crate vs Python re) and Unicode handling can differ. Tests cover the rule pack's documented examples and core helper predicates; if you find a divergence, please open an issue with the input that exposes it.
  3. No LLM-judge fallback: this is the deterministic floor. For semantic-reasoning catches the rule pack misses, layer an LLM-based guardrail downstream (CrewAI also supports those via string-description guardrails).
  4. Retry loop bounded: CrewAI's max_retries (default 3) caps retries. If the agent persistently outputs done_without_evidence, the loop exits with the latest output despite the guardrail blocks. Set max_retries and the task's description accordingly.

Related work

Development

git clone https://github.com/waitdeadai/crewai-no-vibes.git
cd crewai-no-vibes
pip install -e ".[dev]"
pytest

Or without installing (system Python with PEP 668 protection):

PYTHONPATH=src pytest tests/

License

Apache-2.0. See LICENSE.

Author

Fernando Lazzarin · waitdead.com · restlessmachine.com

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

crewai_no_vibes-0.1.0.tar.gz (18.5 kB view details)

Uploaded Source

Built Distribution

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

crewai_no_vibes-0.1.0-py3-none-any.whl (14.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: crewai_no_vibes-0.1.0.tar.gz
  • Upload date:
  • Size: 18.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for crewai_no_vibes-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d40a0dbb6aa3bb583623643905754e06594e610285aed2ca296c7a03400d4d19
MD5 16a0c477fb6ff957ff50f4ab1380d52c
BLAKE2b-256 a08fbc437840e2148b6306ce86c7c735f6723f1bf235b33b168c5e78dfdd57d8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for crewai_no_vibes-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fec63db1b65d344ce4dc3260dd48463fd8f244cce7c9725345a866d81d45ea40
MD5 84eed87edfc783e41d1109be8060424d
BLAKE2b-256 9e4b445cfa4ba27ecba8eb8bc29c13a7dfe1509e7f44cf78ee5b25db1efab9e0

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