Repository navigation
feat(examples): add attribute-based controls example - #302
Open
jasmine-ab-tea wants to merge 6 commits into
Open
jasmine-ab-tea wants to merge 6 commits into
jasmine-ab-tea wants to merge 6 commits into
Conversation
Co-Authored-By: Claude <noreply@anthropic.com>
3 tasks done
- Compare each result to the expected outcome, print PASS/FAIL, and exit non-zero on any mismatch. - Drop the 409 special case on attach. The endpoint is idempotent. - README: describe the PASS/FAIL output. Co-Authored-By: Claude <noreply@anthropic.com>
- Add a baseline control with no jurisdiction condition. It applies to every country, and to requests with no jurisdiction. - Add two scenarios for it: DE + email, and no jurisdiction + email. - Omit step.context when the jurisdiction is missing. - README: explain baseline vs country controls, and copying an x-ai-jurisdiction header into context.jurisdiction. Co-Authored-By: Claude <noreply@anthropic.com>
- Report a server-side control error as ERROR, not BLOCK, in both scripts. - Add a no-jurisdiction + IBAN scenario: country rules are skipped. Co-Authored-By: Claude <noreply@anthropic.com>
jasmine-ab-tea
commented
Nov 5, 2026
jasmine-ab-tea
left a comment
Collaborator
Author
There was a problem hiding this comment.
🤖 This review was generated by the Astra agent (claude-opus-5-5). It may contain mistakes.
Verdict: approve — The round-2 fixes are correct, and I found nothing new that blocks merge.
3 of 4 tasks
The example teaches a general pattern: a rule that applies only for some values of a request attribute. Country is the worked example. Co-Authored-By: Claude <noreply@anthropic.com>
namrataghadi-galileo
pushed a commit
that referenced
this pull request
Nov 5, 2026
## Summary `ci` is red on `main` (run 42083444705, `39140e0`) and on every open PR. mypy reports 3 errors in `evaluators/contrib/galileo/src/agent_control_evaluator_galileo/records/factory.py:159,166,173`. **Cause:** `galileo-core` 4.6.0 (2026-10-30) added `HttpSpan` to its `Span` union. `ToolSpan`, `RetrieverSpan` and `Trace` take `spans: list[Span]`. The evaluator kept its own copy of the union (`GalileoCoreSpan`) without `HttpSpan`. `list` is invariant, so mypy rejects the child-span list. The pin `galileo-core>=4.4.0,<5.0.0` floats, so CI picked up 4.6.1 with no change in this repo. **Fix:** import the SDK's own `Span` alias and drop the local copy. The type then follows whichever `galileo-core` is installed. `Span` exists in every version the pin allows (checked 4.4.0 and 4.6.1). No runtime change: the module uses `from __future__ import annotations`. ## Test plan - [x] mypy on `evaluators/contrib/galileo/src` against `galileo-core` 4.6.1: no errors in this package. Unpatched `main` reproduces the 3 CI errors with the same setup. - [x] mypy against `galileo-core` 4.4.0 (the floor): no errors in this package. - [x] `ruff check` passes. - [ ] CI. Note: the private package index returned 401 locally, so I could not run `make sync`. I ran mypy with the extracted `galileo-core` wheels on `MYPYPATH`, not through `uv run`. The only other errors in that setup are inside `galileo_core` itself, which an installed package does not report. ## Related PRs | Repo | PR | Purpose | Status | |------|----|---------|--------| | agentcontrol/agent-control | this PR | Fix red `ci` on `main` | in review | | agentcontrol/agent-control | #302 | Country controls example, blocked by this `ci` failure | in review | 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ticket: SAO-17024
Summary
This PR adds
examples/attribute_controls/. The example shows how to apply a rule only when a request attribute has a given value. It uses the country (jurisdiction) as the attribute. The same pattern works for tenant, user tier or channel.and(jurisdiction in [CC], rule).or(and(DE, IBAN rule), and(US, SSN rule)).attribute_controls_context.py:evaluate_controls(..., context={"jurisdiction": "DE"}), selected withcontext.jurisdiction.attribute_controls_decorator.py:@control(step_type="tool")with ajurisdictionargument, selected withinput.jurisdiction.examples/README.mdthat links the docs page.The example needs no LLM, no API key and no external service. Each script creates its agent and controls, and is safe to re-run. It prints PASS or FAIL for each check, and exits non-zero on any failure.
Test plan
ruff checkandruff format --checkonexamples/attribute_controls/.Note:
make syncwas not available locally (private package index auth). I verified against the publishedgalileoai/agent-control-serverimage (v8.15.0) started with the rootdocker-compose.yml, not againstmake server-run.Related PRs
examples/attribute-based-controlscionmain(galileo-core 4.6HttpSpanmypy error), needed for this PR'sci🤖 Generated with Claude Code