Skip to content

Commit f63b8b4

Browse files
committed
refactor: collapse advisory control actions to observe
1 parent 14d4c87 commit f63b8b4

64 files changed

Lines changed: 5050 additions & 4933 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ Blocked: block-ssn-demo
231231
Explore working examples for popular frameworks.
232232

233233
- [Customer Support Agent](examples/customer_support_agent/) - PII protection, prompt injection defense, and tool controls
234-
- [Steer Action Demo](examples/steer_action_demo/) - allow, deny, warn, and steer decisions in one workflow
234+
- [Steer Action Demo](examples/steer_action_demo/) - observe, deny, and steer decisions in one workflow
235235
- [LangChain](examples/langchain/) - protect a SQL agent from dangerous queries
236236
- [CrewAI](examples/crewai/) - combine Agent Control with CrewAI guardrails
237237
- [AWS Strands](examples/strands_agents/) - protect Strands workflows and tool calls

‎engine/tests/test_core.py‎

Lines changed: 76 additions & 76 deletions
Large diffs are not rendered by default.

‎examples/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ This directory contains runnable examples for Agent Control. Each example has it
1515
| DeepEval | Build a custom evaluator using DeepEval GEval metrics. | https://docs.agentcontrol.dev/examples/deepeval |
1616
| Galileo Luna-2 | Toxicity detection and content moderation with Galileo Protect. | https://docs.agentcontrol.dev/examples/galileo-luna2 |
1717
| LangChain SQL Agent | Protect a SQL agent from dangerous queries with server-side controls. | https://docs.agentcontrol.dev/examples/langchain-sql |
18-
| Steer Action Demo | Banking transfer agent showcasing allow, deny, warn, and steer actions. | https://docs.agentcontrol.dev/examples/steer-action-demo |
18+
| Steer Action Demo | Banking transfer agent showcasing observe, deny, and steer actions. | https://docs.agentcontrol.dev/examples/steer-action-demo |
1919
| AWS Strands | Guardrails for AWS Strands agent workflows and tool calls. | https://docs.agentcontrol.dev/examples/aws-strands |
2020
| TypeScript SDK | Consumer-style TypeScript example using the published npm package. | https://docs.agentcontrol.dev/examples/typescript_sdk |
2121

‎examples/crewai/README.md‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Tool executes (LLM call, DB query, etc.)
2525
CrewAI Guardrails (quality retries) <- LAYER 3: CrewAI validates quality
2626
|
2727
v
28-
Return to user (or block / steer / warn)
28+
Return to user (or block / steer / observe)
2929
```
3030

3131
**Agent Control** blocks or steers immediately (security). **CrewAI Guardrails** retry with feedback (quality). Controls are defined on the **server** -- update rules without redeploying agents.
@@ -77,15 +77,15 @@ uv run --active python -m secure_research_crew.main
7777

7878
## Examples
7979

80-
### 1. [Steering Financial Agent](./steering_financial_agent/) -- Deny, Steer & Warn
80+
### 1. [Steering Financial Agent](./steering_financial_agent/) -- Deny, Steer & Observe
8181

8282
Demonstrates all three Agent Control action types in a wire-transfer scenario:
8383

8484
| Action | Behavior | Example |
8585
|--------|----------|---------|
8686
| **DENY** | Hard block, no recovery | Sanctioned country, fraud detected |
8787
| **STEER** | Pause, guide agent to correct, retry | 2FA required, manager approval needed |
88-
| **WARN** | Log for audit, no blocking | New recipient, unusual activity |
88+
| **OBSERVE** | Record for audit, no blocking | New recipient, unusual activity |
8989

9090
```bash
9191
cd examples/crewai/steering_financial_agent
@@ -131,7 +131,7 @@ A production-quality **3-agent sequential crew** (Researcher, Analyst, Writer) w
131131

132132
| # | Scenario | Agent | Evaluator | Action | Result |
133133
|---|----------|-------|-----------|--------|--------|
134-
| 1 | Happy path | All 3 | All | allow | Report generated with sources |
134+
| 1 | Happy path | All 3 | All | observe | Report generated with sources |
135135
| 2 | SQL injection | Researcher | SQL | deny | "Multiple SQL statements not allowed" |
136136
| 3 | Restricted table | Researcher | LIST | deny | salary_data access blocked |
137137
| 4 | Missing methodology | Analyst | JSON Schema | steer | Auto-corrected, passes on retry |
@@ -189,7 +189,7 @@ uv run --active python -m content_publishing_flow.main
189189
| POST-execution checks | Yes | Yes | Yes | Yes |
190190
| **deny** action | Yes | Yes | Yes | Yes |
191191
| **steer** action | Yes | Yes | Yes | Yes |
192-
| **warn** action | Yes | | | |
192+
| **observe** action | Yes | | | |
193193
| Regex evaluator | | Yes | Yes | Yes |
194194
| List evaluator | Yes | Yes | Yes | Yes |
195195
| JSON evaluator | Yes | Yes | Yes | Yes |

‎examples/crewai/content_publishing_flow/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ Agent Control works at the **tool boundary** within each flow stage:
129129
3. The server evaluates controls matching the step name and stage (pre/post)
130130
4. On **deny**: `ControlViolationError` is raised, the stage handles it
131131
5. On **steer**: `ControlSteerError` provides corrective guidance for retry
132-
6. On **allow**: execution proceeds normally
132+
6. On **observe** or no match: execution proceeds normally
133133

134134
This pattern means controls are defined on the **server** (not in code), so you can update rules, add new controls, or change actions without redeploying the agent.
135135

‎examples/crewai/secure_research_crew/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Each tool's `step_name` matches the `step_names` in its corresponding control sc
4646

4747
| # | Scenario | Agent | Control | Evaluator | Action | Expected |
4848
|---|----------|-------|---------|-----------|--------|----------|
49-
| 1 | Happy path | All | All | All | allow | Report generated |
49+
| 1 | Happy path | All | All | All | observe | Report generated |
5050
| 2 | SQL injection | Researcher | researcher-sql-safety | SQL | deny | Query blocked |
5151
| 3 | Restricted table | Researcher | researcher-restricted-tables | LIST | deny | Query blocked |
5252
| 4 | Missing methodology | Analyst | analyst-methodology-check | JSON Schema | steer | Auto-corrected, then passes |

‎examples/crewai/steering_financial_agent/README.md‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
# CrewAI Financial Agent with Steering Controls
22

3-
Demonstrates all Agent Control action types in a realistic wire-transfer scenario using CrewAI.
3+
Demonstrates Agent Control actions in a realistic wire-transfer scenario using CrewAI.
44

55
## Action Types
66

77
| Action | Behavior | Example |
88
|--------|----------|---------|
99
| **DENY** | Hard block, agent cannot recover | Sanctioned country, fraud detected |
1010
| **STEER** | Pause execution, guide agent to correct and retry | 2FA required, manager approval needed |
11-
| **WARN** | Log for audit, agent continues uninterrupted | New recipient, unusual activity |
11+
| **OBSERVE** | Record for audit, agent continues uninterrupted | New recipient, unusual activity |
1212

13-
The key difference: **DENY** raises `ControlViolationError` (permanent), **STEER** raises `ControlSteerError` (recoverable), and **WARN** logs silently.
13+
The key difference: **DENY** raises `ControlViolationError` (permanent), **STEER** raises `ControlSteerError` (recoverable), and **OBSERVE** records a non-blocking advisory event.
1414

1515
## Scenarios
1616

1717
| # | Scenario | Amount | Controls Triggered | Outcome |
1818
|---|----------|--------|--------------------|---------|
19-
| 1 | Small transfer to new vendor | $2,500 | warn (new recipient) | ALLOWED + audit log |
19+
| 1 | Small transfer to new vendor | $2,500 | observe (new recipient) | ALLOWED + audit trail |
2020
| 2 | Transfer to North Korea | $500 | deny (sanctioned country) | BLOCKED |
2121
| 3 | Large transfer | $15,000 | steer (2FA required) | STEERED -> verified -> ALLOWED |
2222
| 4 | Very large transfer | $75,000 | steer (2FA + manager) | STEERED -> approved -> ALLOWED |
@@ -28,8 +28,8 @@ The key difference: **DENY** raises `ControlViolationError` (permanent), **STEER
2828
- `deny-high-fraud-score` — JSON evaluator, blocks fraud_score > 0.8
2929
- `steer-require-2fa` — JSON evaluator with oneOf schema, steers for 2FA
3030
- `steer-require-manager-approval` — JSON evaluator, steers for approval
31-
- `warn-new-recipient` — LIST evaluator, logs unknown recipients
32-
- `warn-pii-in-confirmation` — REGEX evaluator, logs PII in output
31+
- `observe-new-recipient` — LIST evaluator, records unknown recipients
32+
- `observe-pii-in-confirmation` — REGEX evaluator, records PII in output
3333

3434
## Prerequisites
3535

‎examples/crewai/steering_financial_agent/pyproject.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[project]
22
name = "steering-financial-agent"
33
version = "0.1.0"
4-
description = "CrewAI financial agent with steering, deny, and warn actions via Agent Control"
4+
description = "CrewAI financial agent with steering, deny, and observe actions via Agent Control"
55
requires-python = ">=3.12"
66
dependencies = [
77
"agent-control-sdk>=6.3.0",

‎examples/crewai/steering_financial_agent/setup_controls.py‎

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
"""
22
Setup script for the CrewAI Financial Agent steering example.
33
4-
Creates controls that demonstrate all three non-blocking action types:
4+
Creates controls that demonstrate the three supported action types:
55
- DENY: Hard-block sanctioned countries and fraud (no recovery)
66
- STEER: Guide the agent through 2FA and manager approval workflows
7-
- WARN: Flag new recipients and unusual hours for audit (no blocking)
7+
- OBSERVE: Flag new recipients and unusual hours for audit (no blocking)
88
99
Run once before running the agent:
1010
uv run --active python setup_controls.py
@@ -222,15 +222,15 @@ async def setup():
222222
},
223223
),
224224
# ┌─────────────────────────────────────────────────────────┐
225-
# │ WARN: New Recipient │
225+
# │ OBSERVE: New Recipient │
226226
# │ Uses LIST evaluator with "not in" logic. │
227-
# │ Logs a warning when recipient is unknown — but does │
228-
# │ NOT block the transfer. Useful for audit trails. │
227+
# │ Records an advisory event when recipient is unknown │
228+
# │ but does NOT block the transfer. Useful for audit. │
229229
# └─────────────────────────────────────────────────────────┘
230230
(
231-
"warn-new-recipient",
231+
"observe-new-recipient",
232232
{
233-
"description": "Log warning for transfers to unknown recipients",
233+
"description": "Observe transfers to unknown recipients",
234234
"enabled": True,
235235
"execution": "server",
236236
"scope": {
@@ -251,18 +251,18 @@ async def setup():
251251
"case_sensitive": False,
252252
},
253253
},
254-
"action": {"decision": "warn"},
254+
"action": {"decision": "observe"},
255255
},
256256
),
257257
# ┌─────────────────────────────────────────────────────────┐
258-
# │ WARN: PII in Output │
258+
# │ OBSERVE: PII in Output │
259259
# │ Uses REGEX evaluator to detect leaked PII in the │
260-
# │ transfer confirmation. Logs for compliance review. │
260+
# │ transfer confirmation. Records for compliance review. │
261261
# └─────────────────────────────────────────────────────────┘
262262
(
263-
"warn-pii-in-confirmation",
263+
"observe-pii-in-confirmation",
264264
{
265-
"description": "Log warning if transfer confirmation contains PII patterns",
265+
"description": "Observe PII patterns in transfer confirmation output",
266266
"enabled": True,
267267
"execution": "server",
268268
"scope": {
@@ -277,7 +277,7 @@ async def setup():
277277
"pattern": r"(?:\b\d{3}-\d{2}-\d{4}\b|\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b)"
278278
},
279279
},
280-
"action": {"decision": "warn"},
280+
"action": {"decision": "observe"},
281281
},
282282
),
283283
]
@@ -322,7 +322,7 @@ async def setup():
322322
print(" - 2FA required for >= $10k (json evaluator)")
323323
print(" - Manager approval for >= $50k (json evaluator)")
324324
print()
325-
print(" WARN (log for audit, no blocking):")
325+
print(" OBSERVE (audit trail, no blocking):")
326326
print(" - New/unknown recipient (list evaluator)")
327327
print(" - PII in confirmation output (regex evaluator)")
328328
print()

‎examples/crewai/steering_financial_agent/src/steering_financial_agent/main.py‎

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
"""
2-
CrewAI Financial Agent with Steering, Deny, and Warn actions.
2+
CrewAI Financial Agent with Steering, Deny, and Observe actions.
33
44
Demonstrates the three key Agent Control action types in a realistic
55
wire-transfer scenario using a CrewAI crew:
66
77
DENY - Sanctioned country or fraud score blocks the transfer immediately.
88
STEER - Large transfers pause execution and guide the agent through
99
2FA verification or manager approval before retrying.
10-
WARN - New recipients and PII in output are logged for audit
11-
without blocking the transfer.
10+
OBSERVE - New recipients and PII in output are recorded for audit
11+
without blocking the transfer.
1212
1313
PREREQUISITE:
1414
Run setup_controls.py first:
@@ -20,7 +20,7 @@
2020
$ uv run --active steering_financial_agent
2121
2222
Scenarios:
23-
1. Small legitimate transfer -> ALLOW (warn on new recipient)
23+
1. Small legitimate transfer -> OBSERVE (new recipient)
2424
2. Sanctioned country -> DENY (hard block)
2525
3. Large transfer ($15k) -> STEER (2FA required, then allowed)
2626
4. Very large transfer ($75k) -> STEER (manager approval, then allowed)
@@ -67,7 +67,7 @@ def verify_server():
6767
"deny-high-fraud-score",
6868
"steer-require-2fa",
6969
"steer-require-manager-approval",
70-
"warn-new-recipient",
70+
"observe-new-recipient",
7171
]
7272
missing = [n for n in required if n not in names]
7373
if missing:
@@ -104,7 +104,7 @@ def run_scenario(crew, number, title, request, expected):
104104
def main():
105105
print("=" * 60)
106106
print(" CrewAI Financial Agent")
107-
print(" Steering, Deny & Warn with Agent Control")
107+
print(" Steering, Deny & Observe with Agent Control")
108108
print("=" * 60)
109109
print()
110110

@@ -118,19 +118,19 @@ def main():
118118
crew = create_financial_crew()
119119

120120
# ── Scenario 1: Small Legitimate Transfer ───────────────────────
121-
# Amount < $10k, known country, low fraud → ALLOW
122-
# Unknown recipient → WARN (logged, not blocked)
121+
# Amount < $10k, known country, low fraud → OBSERVE only
122+
# Unknown recipient → OBSERVE (recorded, not blocked)
123123
run_scenario(
124124
crew,
125125
1,
126-
"Small Legitimate Transfer (ALLOW + WARN)",
126+
"Small Legitimate Transfer (OBSERVE)",
127127
{
128128
"amount": 2500,
129129
"recipient": "New Vendor XYZ",
130130
"destination_country": "Germany",
131131
"fraud_score": 0.1,
132132
},
133-
"ALLOWED with warning (new recipient logged for audit)",
133+
"Allowed with an observe event (new recipient recorded for audit)",
134134
)
135135

136136
# ── Scenario 2: Sanctioned Country ──────────────────────────────
@@ -149,26 +149,26 @@ def main():
149149
)
150150

151151
# ── Scenario 3: Large Transfer Requiring 2FA ────────────────────
152-
# Amount $15k → STEER (2FA required), agent verifies, retries → ALLOW
152+
# Amount $15k → STEER (2FA required), agent verifies, retries successfully
153153
run_scenario(
154154
crew,
155155
3,
156-
"Large Transfer - 2FA Steering (STEER then ALLOW)",
156+
"Large Transfer - 2FA Steering (STEER then success)",
157157
{
158158
"amount": 15000,
159159
"recipient": "Acme Corp",
160160
"destination_country": "United Kingdom",
161161
"fraud_score": 0.2,
162162
},
163-
"STEERED (2FA), then ALLOWED after verification",
163+
"STEERED (2FA), then succeeded after verification",
164164
)
165165

166166
# ── Scenario 4: Very Large Transfer Requiring Manager Approval ──
167-
# Amount $75k → STEER (2FA + manager approval), agent handles both → ALLOW
167+
# Amount $75k → STEER (2FA + manager approval), agent handles both successfully
168168
run_scenario(
169169
crew,
170170
4,
171-
"Very Large Transfer - Manager Approval (STEER then ALLOW)",
171+
"Very Large Transfer - Manager Approval (STEER then success)",
172172
{
173173
"amount": 75000,
174174
"recipient": "Global Suppliers Inc",
@@ -206,13 +206,13 @@ def main():
206206
STEER 2FA verification (Scenario 3) - pause, verify, retry
207207
Manager approval (Scenario 4) - pause, collect + approve, retry
208208
209-
WARN New recipient (Scenario 1) - logged for audit, not blocked
210-
PII in output (if triggered) - logged for compliance, not blocked
209+
OBSERVE New recipient (Scenario 1) - recorded for audit, not blocked
210+
PII in output (if triggered) - recorded for compliance, not blocked
211211
212212
Key Differences:
213213
DENY = ControlViolationError (agent cannot recover)
214214
STEER = ControlSteerError (agent corrects and retries)
215-
WARN = Logged silently (agent continues uninterrupted)
215+
OBSERVE = Recorded silently (agent continues uninterrupted)
216216
""")
217217

218218

0 commit comments

Comments
 (0)