Skip to content

feat(examples): add attribute-based controls example - #302

Open
jasmine-ab-tea wants to merge 6 commits into
mainfrom
docs/country-controls-example
Open

jasmine-ab-tea wants to merge 6 commits into
mainfrom
docs/country-controls-example

Conversation

@jasmine-ab-tea

@jasmine-ab-tea jasmine-ab-tea commented Nov 5, 2026 •

Copy link
Copy Markdown
Collaborator

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.

  • Two authoring styles for the same policy, run side by side:
    • One control per value (here, per country): and(jurisdiction in [CC], rule).
    • One composite control: or(and(DE, IBAN rule), and(US, SSN rule)).
  • A baseline control next to the attribute-based controls. It has no jurisdiction condition, so it applies to every country and to requests with no jurisdiction.
  • Two ways to send the jurisdiction:
    • attribute_controls_context.py: evaluate_controls(..., context={"jurisdiction": "DE"}), selected with context.jurisdiction.
    • attribute_controls_decorator.py: @control(step_type="tool") with a jurisdiction argument, selected with input.jurisdiction.
  • A row in examples/README.md that 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 check and ruff format --check on examples/attribute_controls/.
  • Ran both scripts against a local server. Each passes 16/16 checks: 8 scenarios (DE+IBAN block, US+IBAN allow, US+SSN block, DE+SSN allow, US+clean allow, DE+email block, no jurisdiction+IBAN allow, no jurisdiction+email block), for both the per-country and the composite controls.
  • Changed one expected value to check the failure path: the script prints FAIL and exits 1.
  • Re-ran both scripts against the same database. The upsert path (409, then update) works.

Note: make sync was not available locally (private package index auth). I verified against the published galileoai/agent-control-server image (v8.15.0) started with the root docker-compose.yml, not against make server-run.

Related PRs

Repo PR Purpose Status
agentcontrol/agent-control this PR Example scripts and README in review
agentcontrol/docs-agent-control agentcontrol/docs-agent-control#43 Docs page examples/attribute-based-controls in review
agentcontrol/agent-control #303 Fix red ci on main (galileo-core 4.6 HttpSpan mypy error), needed for this PR's ci in review

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
jasmine-ab-tea and others added 3 commits November 5, 2026 11:01
- 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 jasmine-ab-tea left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🤖 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.

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>
@jasmine-ab-tea jasmine-ab-tea changed the title feat(examples): add country-specific controls example feat(examples): add attribute-based controls example Nov 5, 2026
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

codecov Bot commented Nov 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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.

1 participant