Skip to content

fix: Feature Idea: Deterministic arbitration/escrow for agent-to-agent transactions - #6792

Open
ojassharma7 wants to merge 2 commits into
crewAIInc:mainfrom
ojassharma7:autocontrib/issue-6782
Open

fix: Feature Idea: Deterministic arbitration/escrow for agent-to-agent transactions#6792
ojassharma7 wants to merge 2 commits into
crewAIInc:mainfrom
ojassharma7:autocontrib/issue-6782

Conversation

@ojassharma7

Copy link
Copy Markdown

Fixes #6782.

What changed

  • docs/edge/en/concepts/tasks.mdx
  • lib/crewai/src/crewai/__init__.py
  • lib/crewai/src/crewai/events/types/llm_guardrail_events.py
  • lib/crewai/src/crewai/tasks/arbitration.py
  • lib/crewai/tests/test_arbitration.py

Verification

The project's own test suite was run before and after this change; it introduces no new test failures or lint violations.

Copilot AI review requested due to automatic review settings August 3, 2026 19:03
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 83282737-6a5d-48c6-abbc-00f3281fe4be

📥 Commits

Reviewing files that changed from the base of the PR and between b54e5c0 and e3e403a.

📒 Files selected for processing (2)
  • docs/edge/en/concepts/tasks.mdx
  • lib/crewai/src/crewai/tasks/arbitration.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • docs/edge/en/concepts/tasks.mdx
  • lib/crewai/src/crewai/tasks/arbitration.py

📝 Walkthrough

Walkthrough

Changes

Deterministic arbitration validates task deliverables against Pydantic contracts, deadlines, and optional CEL rules. It returns structured approval or dispute results, integrates with task guardrails and events, exposes public APIs, and includes tests and documentation.

Deterministic arbitration

Layer / File(s) Summary
Arbitration result and evaluation pipeline
lib/crewai/src/crewai/tasks/arbitration.py
The arbitration engine coerces supported payloads, validates contracts, checks deadlines, evaluates CEL rules, and returns structured results.
Guardrail integration and public wiring
lib/crewai/src/crewai/tasks/arbitration.py, lib/crewai/src/crewai/__init__.py, lib/crewai/src/crewai/events/types/llm_guardrail_events.py
ArbitrationGuardrail returns serialized approved data or retry instructions. Arbitration types are publicly exported and classified in guardrail events.
Contract and behavior validation
lib/crewai/tests/test_arbitration.py
Tests cover valid and invalid payloads, JSON parsing, deadlines, CEL rules, TaskOutput, disputes, serialization, and task retries.
Arbitration guardrail documentation
docs/edge/en/concepts/tasks.mdx
Documentation describes deterministic arbitration and its contracts, rules, deadlines, approvals, and disputes.

Sequence Diagram(s)

sequenceDiagram
  participant Task
  participant ArbitrationGuardrail
  participant ArbitrationEngine
  participant Contract
  Task->>ArbitrationGuardrail: submit TaskOutput
  ArbitrationGuardrail->>ArbitrationEngine: evaluate payload
  ArbitrationEngine->>Contract: validate payload
  Contract-->>ArbitrationEngine: validated payload or violations
  ArbitrationEngine-->>ArbitrationGuardrail: approved or disputed result
  ArbitrationGuardrail-->>Task: serialized output or retry instructions
Loading

Suggested reviewers: copilot

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the deterministic arbitration feature for agent-to-agent transactions.
Description check ✅ Passed The description lists the changed files and verification results for the arbitration implementation.
Linked Issues check ✅ Passed The changes implement deterministic deliverable arbitration with Pydantic validation, logical rules, deadlines, JSON checks, violations, and task guardrail integration [#6782].
Out of Scope Changes check ✅ Passed The documentation, exports, event classification, arbitration module, and tests all support the linked issue objectives [#6782].
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a deterministic “arbitration/escrow” mechanism for agent deliverables, allowing task outputs to be validated against hard constraints (Pydantic contracts, optional CEL rules, and deadlines) before a task is considered resolved.

Changes:

  • Adds a new ArbitrationEngine + ArbitrationGuardrail implementation for deterministic validation/dispute outcomes.
  • Exposes the new arbitration types at the crewai top-level API and integrates them into guardrail-start event classification.
  • Documents the new guardrail type and adds a dedicated test suite covering approval/dispute cases, CEL rule evaluation, and retry behavior.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
docs/edge/en/concepts/tasks.mdx Documents deterministic arbitration guardrails as a new guardrail type with an example.
lib/crewai/src/crewai/init.py Re-exports arbitration engine/guardrail/result types as part of the public API.
lib/crewai/src/crewai/events/types/llm_guardrail_events.py Classifies ArbitrationGuardrail in guardrail-start events (guardrail_type="arbitration").
lib/crewai/src/crewai/tasks/arbitration.py Implements deterministic arbitration evaluation (Pydantic validation, optional CEL rules, deadlines) and a Task guardrail wrapper.
lib/crewai/tests/test_arbitration.py Adds tests for approved/disputed outcomes, invalid JSON handling, deadline disputes, CEL rule pass/fail, and retry integration.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +255 to +259
from typing import cast

from celpy import Environment
from celpy.adapter import CELJSONEncoder, json_to_cel
from celpy.evaluation import Context
parts.append(f"deadline={self.deadline.isoformat()}")
return " ".join(parts)

def __call__(self, task_output: TaskOutput):

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (3)
lib/crewai/src/crewai/tasks/arbitration.py (2)

262-271: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Optional: cache the compiled CEL programs.

_evaluate_rules builds a new Environment and recompiles every rule on each evaluate call. A guardrail with fixed rules recompiles on every task retry. Consider compiling once per rule set and caching the programs on ArbitrationEngine.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/crewai/src/crewai/tasks/arbitration.py` around lines 262 - 271, Update
ArbitrationEngine._evaluate_rules to cache compiled CEL programs for each fixed
rule set instead of creating a new Environment and recompiling rules on every
evaluation. Store and reuse the compiled programs on the ArbitrationEngine
instance, while preserving rule trimming, empty-rule skipping, and evaluation
behavior.

347-347: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Annotate the __call__ return type for the guardrail callable contract.

ArbitrationGuardrail.__call__ is the callable that Task(guardrail=...) passes as the guardrail, and it returns a (bool, str) tuple. GuardrailCallable has the same signature, so use GuardrailCallable or tuple[bool, str | TaskOutput] to express the contract.

♻️ Proposed change
-    def __call__(self, task_output: TaskOutput):
+    def __call__(self, task_output: TaskOutput) -> tuple[bool, str | TaskOutput]:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/crewai/src/crewai/tasks/arbitration.py` at line 347, Update
ArbitrationGuardrail.__call__ to annotate its return type with the existing
GuardrailCallable contract, or the equivalent tuple[bool, str | TaskOutput]
type, while preserving its current behavior.

Source: Coding guidelines

docs/edge/en/concepts/tasks.mdx (1)

374-377: 🗄️ Data Integrity & Integration | 🔵 Trivial

Clarify the external payment boundary.

ArbitrationGuardrail.__call__ only validates the task output and returns a result. It does not bind approval to a transaction or release funds. Document that the caller must persist the decision, bind it to a transaction or version, and use replay-safe, idempotent payment handling.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/edge/en/concepts/tasks.mdx` around lines 374 - 377, Update the outcomes
and release-gate documentation near ArbitrationGuardrail.__call__ to state that
the method only validates task output and returns a result; the caller must
persist the decision, bind it to the relevant transaction or task version, and
use replay-safe, idempotent handling when releasing funds through an external
payment rail.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/edge/en/concepts/tasks.mdx`:
- Around line 374-376: Update the Outcomes description in the task concepts
documentation to replace “field-level violations” with “structured violations,”
while preserving the listed payload-level, deadline, and validation error
examples.
- Around line 356-367: Align the HotelBooking price constraint with the task
wording by enforcing a strict upper bound: change the price_per_night field in
HotelBooking to use lt=180 and update the ArbitrationGuardrail rule to
price_per_night < 180.0. Preserve the existing “under $180/night” description.
- Around line 355-370: Update the HotelBooking contract and escrow_guardrail so
the non-smoking requirement is enforceable: add a smoking-status field with an
explicit non-smoking constraint and include the corresponding guardrail rule, or
remove “non-smoking” from booking_task.description. Keep the task description,
output schema, and guardrail rules consistent.
- Around line 360-364: Update the escrow_guardrail setup around
ArbitrationGuardrail so its deadline is calculated at handoff or execution start
rather than when the task configuration is constructed. Create the guardrail
through a function that receives the handoff timestamp, or reuse the task
transaction’s execution timestamp, and preserve the one-hour deadline window.
- Around line 355-363: Update HotelBooking.price_per_night to enforce a
non-negative value with a Pydantic lower bound of zero, and extend
escrow_guardrail’s CEL rules with the corresponding price_per_night >= 0
constraint while preserving the existing upper-bound validation.

In `@lib/crewai/tests/test_arbitration.py`:
- Around line 139-167: Extend the arbitration tests around
`test_evaluate_accepts_task_output_json_dict` with approval cases for
`TaskOutput.pydantic` and valid JSON supplied through `TaskOutput.raw`,
preserving the same `CodeReviewOutputContract` behavior. In
`test_guardrail_call_approves_and_returns_json`, deserialize `value` with
`json.loads` and assert it equals `valid_payload` instead of checking for a
serialized substring.
- Around line 66-84: Update test_evaluate_disputes_invalid_payload to verify
each invalid field produces its expected structured contract violation rather
than only asserting that at least one violation exists. Assert violations for
the invalid task_id, summary, confidence_score, blocking_issues_found, status,
and unexpected_field while preserving the existing disputed, approval, and
retry-instruction assertions; alternatively, parameterize isolated invalid
payloads to test each constraint independently.

---

Nitpick comments:
In `@docs/edge/en/concepts/tasks.mdx`:
- Around line 374-377: Update the outcomes and release-gate documentation near
ArbitrationGuardrail.__call__ to state that the method only validates task
output and returns a result; the caller must persist the decision, bind it to
the relevant transaction or task version, and use replay-safe, idempotent
handling when releasing funds through an external payment rail.

In `@lib/crewai/src/crewai/tasks/arbitration.py`:
- Around line 262-271: Update ArbitrationEngine._evaluate_rules to cache
compiled CEL programs for each fixed rule set instead of creating a new
Environment and recompiling rules on every evaluation. Store and reuse the
compiled programs on the ArbitrationEngine instance, while preserving rule
trimming, empty-rule skipping, and evaluation behavior.
- Line 347: Update ArbitrationGuardrail.__call__ to annotate its return type
with the existing GuardrailCallable contract, or the equivalent tuple[bool, str
| TaskOutput] type, while preserving its current behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e52d0b79-26a4-48c8-8c4f-98b59ee6ed66

📥 Commits

Reviewing files that changed from the base of the PR and between c8f441c and b54e5c0.

📒 Files selected for processing (5)
  • docs/edge/en/concepts/tasks.mdx
  • lib/crewai/src/crewai/__init__.py
  • lib/crewai/src/crewai/events/types/llm_guardrail_events.py
  • lib/crewai/src/crewai/tasks/arbitration.py
  • lib/crewai/tests/test_arbitration.py

Comment thread docs/edge/en/concepts/tasks.mdx
Comment thread docs/edge/en/concepts/tasks.mdx
Comment thread docs/edge/en/concepts/tasks.mdx Outdated
Comment on lines +360 to +364
escrow_guardrail = ArbitrationGuardrail(
HotelBooking,
rules=["output.price_per_night <= 180.0"],
deadline=datetime.now(timezone.utc) + timedelta(hours=1),
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Locate file and surrounding context =="
if [ -f docs/edge/en/concepts/tasks.mdx ]; then
  sed -n '320,390p' docs/edge/en/concepts/tasks.mdx | cat -n
else
  fd -i 'tasks.mdx' .
fi

echo "== Search for ArbitrationGuardrail usage and deadline semantics =="
rg -n "ArbitrationGuardrail|deadline|handoff|task execution|execution" docs/edge/en/concepts/tasks.mdx . --glob '!dist/**' --glob '!build/**' | sed -n '1,220p'

echo "== Search for source definition if present in repo =="
fd -i "guardrail|arbitration" . | sed -n '1,80p'
rg -n "class ArbitrationGuardrail|def .*deadline|deadline" . --glob '!dist/**' --glob '!build/**' | sed -n '1,220p'

Repository: crewAIInc/crewAI

Length of output: 36553


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Arbitration implementation =="
sed -n '288,355p' lib/crewai/src/crewai/tasks/arbitration.py | cat -n
sed -n '60,132p' lib/crewai/src/crewai/tasks/arbitration.py | cat -n

echo "== Guardrail evaluation call sites =="
rg -n "guardrail\s*=|if guardrail|guardrail\(" lib/crewai/src/crewai -g '*.py' | sed -n '1,220p'
rg -n "ArbitrationGuardrail|evaluate\(" lib/crewai/src/crewai/src lib/crewai/src/crewai -g '*.py' | sed -n '1,220p'

echo "== Guardrail tests around deadline semantics =="
sed -n '80,115p' lib/crewai/tests/test_arbitration.py | cat -n

echo "== Deterministic probe: guardrail configuration vs evaluation time =="
python3 - <<'PY'
from datetime import datetime, timedelta, timezone

deadline_configured_at = datetime(2020_01_01, 12, 0, tzinfo=timezone.utc)
deadline = deadline_configured_at + timedelta(hours=1)
task_executes_at = deadline + timedelta(minutes=10)

print("constructed deadline:", deadline == deadline_configured_at + timedelta(hours=1))
print("evaluation after deadline:", task_executes_at > deadline)
print("fixed deadline allows 70 minutes after construction:", task_executes_at - deadline_configured_at)
print("relative handoff deadline from execution would be:", timedelta(hours=1), "<", (task_executes_at - task_executes_at).total_seconds())
PY

Repository: crewAIInc/crewAI

Length of output: 13919


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Guardrail dispatcher and arbitration callable =="
sed -n '115,185p' lib/crewai/src/crewai/utilities/guardrail.py | cat -n
sed -n '355,385p' lib/crewai/src/crewai/tasks/arbitration.py | cat -n

echo "== Guardrail tests about miss timing =="
sed -n '88,110p' lib/crewai/tests/test_arbitration.py | cat -n

echo "== Deterministic probe of construction-bound deadline behavior =="
python3 - <<'PY'
from datetime import datetime, timedelta, timezone

constructed_at = datetime(2026, 1, 1, 0, 0, tzinfo=timezone.utc)
fixed_deadline = constructed_at + timedelta(hours=1)
handoff_and_submission = fixed_deadline + timedelta(minutes=10)

print({
    "fixed_deadline": fixed_deadline.isoformat(),
    "handoff_and_submission": handoff_and_submission.isoformat(),
    "elapsed_between_configuration_and_handoff_minutes": (handoff_and_submission - constructed_at).total_seconds() / 60,
    "deadline_missed_by_runtime_logic": handoff_and_submission > fixed_deadline,
})
PY

Repository: crewAIInc/crewAI

Length of output: 4813


Compute the deadline from handoff time.

datetime.now(timezone.utc) + timedelta(hours=1) is stored when escrow_guardrail is constructed. ArbitrationGuardrail passes that fixed deadline to evaluate, so a 10-minute delay between task configuration and handoff submission triggers deadline_missed. Pass the handoff/execution start timestamp into a function that creates the guardrail, or use a timestamp from the task transaction instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/edge/en/concepts/tasks.mdx` around lines 360 - 364, Update the
escrow_guardrail setup around ArbitrationGuardrail so its deadline is calculated
at handoff or execution start rather than when the task configuration is
constructed. Create the guardrail through a function that receives the handoff
timestamp, or reuse the task transaction’s execution timestamp, and preserve the
one-hour deadline window.

Comment thread docs/edge/en/concepts/tasks.mdx
Comment on lines +66 to +84
def test_evaluate_disputes_invalid_payload(engine: ArbitrationEngine) -> None:
bad_payload = {
"task_id": "not-a-uuid",
"status": "done",
"summary": "too short",
"confidence_score": 1.4,
"files_reviewed": [],
"blocking_issues_found": -3,
"unexpected_field": "hack attempt",
}

result = engine.evaluate(CodeReviewOutputContract, bad_payload)

assert result.status is ArbitrationStatus.DISPUTED
assert not result.is_approved
assert len(result.violations) >= 1
instructions = result.to_retry_instructions()
assert "DISPUTED" in instructions
assert "constraint=" in instructions

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Assert each contract violation.

Line 81 passes if any one invalid field still causes a dispute. It does not verify the required-field, range, custom-status, or extra-field contract checks independently.

Assert the expected violation fields, or parameterize isolated invalid payloads. This verifies each hard constraint and its structured dispute output.

Proposed assertion
     assert result.status is ArbitrationStatus.DISPUTED
     assert not result.is_approved
-    assert len(result.violations) >= 1
+    assert {
+        violation.field for violation in result.violations
+    } >= {
+        "status",
+        "summary",
+        "confidence_score",
+        "files_reviewed",
+        "blocking_issues_found",
+        "unexpected_field",
+    }

As per coding guidelines, unit tests for new functionality must focus on behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/crewai/tests/test_arbitration.py` around lines 66 - 84, Update
test_evaluate_disputes_invalid_payload to verify each invalid field produces its
expected structured contract violation rather than only asserting that at least
one violation exists. Assert violations for the invalid task_id, summary,
confidence_score, blocking_issues_found, status, and unexpected_field while
preserving the existing disputed, approval, and retry-instruction assertions;
alternatively, parameterize isolated invalid payloads to test each constraint
independently.

Source: Coding guidelines

Comment on lines +139 to +167
def test_evaluate_accepts_task_output_json_dict(
engine: ArbitrationEngine, valid_payload: dict
) -> None:
task_output = TaskOutput(
description="Review code",
agent="reviewer",
raw="ignored when json_dict is set",
json_dict=valid_payload,
)

result = engine.evaluate(CodeReviewOutputContract, task_output)

assert result.is_approved


def test_guardrail_call_approves_and_returns_json(valid_payload: dict) -> None:
guardrail = ArbitrationGuardrail(CodeReviewOutputContract)
task_output = TaskOutput(
description="Review code",
agent="reviewer",
raw=str(valid_payload),
json_dict=valid_payload,
)

ok, value = guardrail(task_output)

assert ok is True
assert '"status": "completed"' in value
assert "ArbitrationGuardrail(CodeReviewOutputContract)" in guardrail.description

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Cover all supported TaskOutput paths and validate serialized JSON.

This test covers only TaskOutput.json_dict. The arbitration engine also accepts TaskOutput.pydantic and valid JSON in TaskOutput.raw.

Add approval tests for those inputs. Replace the substring check at Line 166 with json.loads(value) == valid_payload to verify the guardrail output contract.

As per coding guidelines, unit tests for new functionality must focus on behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/crewai/tests/test_arbitration.py` around lines 139 - 167, Extend the
arbitration tests around `test_evaluate_accepts_task_output_json_dict` with
approval cases for `TaskOutput.pydantic` and valid JSON supplied through
`TaskOutput.raw`, preserving the same `CodeReviewOutputContract` behavior. In
`test_guardrail_call_approves_and_returns_json`, deserialize `value` with
`json.loads` and assert it equals `valid_payload` instead of checking for a
serialized substring.

Source: Coding guidelines

Handle missing celpy as a DISPUTED violation, annotate the guardrail callable, and tighten the docs example constraints.

Co-authored-by: Cursor <cursoragent@cursor.com>
@ojassharma7

Copy link
Copy Markdown
Author

Addressed the actionable Copilot/CodeRabbit notes:

  • Wrap celpy imports in try/except so missing/broken CEL runtime returns a DISPUTED violation instead of crashing
  • Annotate ArbitrationGuardrail.__call__ as tuple[bool, Any]
  • Docs example: ge=0/le=180, enforce non_smoking, align wording to “at most $180/night”, and say “structured violations”

Copilot AI review requested due to automatic review settings August 3, 2026 20:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (3)

docs/edge/en/concepts/tasks.mdx:348

  • The docs introduce optional CEL rules, but don’t mention that CEL evaluation requires an extra dependency (cel-python providing celpy). Without that, any task using rules=[...] will always dispute with a rule evaluation error. Adding a short install note here would prevent confusing retries for users.
For agent-to-agent handoffs where you need machine-speed, auditable decisions
(schema shape, numeric bounds, deadlines) without LLM hallucination risk, use
`ArbitrationGuardrail`. It evaluates the task output against a Pydantic contract
and optional CEL boolean rules, then returns either an approved payload or
precise dispute feedback the agent can retry against.

lib/crewai/src/crewai/tasks/arbitration.py:71

  • to_retry_instructions() only appends the "expected" detail when violation.expected is truthy. If expected is a valid but falsy value (e.g., "0"), it will be omitted from the retry instructions, which makes disputes less actionable.
                f"constraint='{violation.constraint}' -> {violation.message}"
            )
            if violation.expected:
                detail += f" (expected: {violation.expected})"
            lines.append(detail)

lib/crewai/src/crewai/tasks/arbitration.py:346

  • ArbitrationEngine._evaluate_rules() treats a missing CEL runtime as a normal deliverable violation. In a Task guardrail context this triggers retries even though the agent can’t fix a missing dependency, wasting attempts/tokens. Consider failing fast during ArbitrationGuardrail initialization when rules are configured but cel-python/celpy is unavailable.
        self.contract = contract
        self.rules = list(rules) if rules else None
        self.deadline = deadline
        self.engine = engine or ArbitrationEngine()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Idea: Deterministic arbitration/escrow for agent-to-agent transactions

2 participants