Skip to content

Commit cd431f1

Browse files
committed
Phase 4: policy references
1 parent 9a0dde6 commit cd431f1

4 files changed

Lines changed: 664 additions & 1 deletion

File tree

README.md

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,21 +80,112 @@ SecureAgent
8080
└── RuntimeAgent (orchestration, pre-action hook)
8181
```
8282

83-
## Policy Example
83+
## Debug Mode
84+
85+
Debug mode provides human-readable trace output for troubleshooting:
86+
87+
```python
88+
secure_agent = SecureAgent(
89+
agent=agent,
90+
policy="policy.yaml",
91+
mode="debug",
92+
trace_format="console", # or "json"
93+
trace_file="trace.jsonl", # optional file output
94+
)
95+
```
96+
97+
Console output shows:
98+
- Session start/end with framework and policy info
99+
- Each step with action and resource
100+
- Policy decisions (ALLOWED/DENIED) with reason codes
101+
- Snapshot diffs (before/after state changes)
102+
- Verification results (PASS/FAIL)
103+
104+
For JSON trace output (machine-parseable):
105+
106+
```python
107+
secure_agent = SecureAgent(
108+
agent=agent,
109+
mode="debug",
110+
trace_format="json",
111+
trace_file="trace.jsonl",
112+
)
113+
```
114+
115+
## Policy Reference
116+
117+
### Basic Structure
118+
119+
```yaml
120+
# policies/example.yaml
121+
rules:
122+
- action: "<action_pattern>"
123+
resource: "<resource_pattern>"
124+
effect: allow | deny
125+
require_verification: # optional
126+
- <predicate>
127+
```
128+
129+
### Action Patterns
130+
131+
| Pattern | Description | Example |
132+
|---------|-------------|---------|
133+
| `browser.*` | All browser actions | click, type, navigate |
134+
| `browser.click` | Specific action | Only click events |
135+
| `api.call` | API tool calls | HTTP requests |
136+
| `*` | Wildcard (all actions) | Catch-all rules |
137+
138+
### Resource Patterns
139+
140+
| Pattern | Description | Example |
141+
|---------|-------------|---------|
142+
| `https://example.com/*` | URL prefix match | All pages on domain |
143+
| `*checkout*` | Contains match | Any checkout-related URL |
144+
| `button#submit` | CSS selector | Specific element |
145+
| `*` | Wildcard (all resources) | Catch-all |
146+
147+
### Verification Predicates
148+
149+
```yaml
150+
require_verification:
151+
# URL checks
152+
- url_contains: "/checkout"
153+
- url_matches: "^https://.*\\.amazon\\.com/.*"
154+
155+
# DOM state checks
156+
- element_exists: "#cart-items"
157+
- element_text_contains:
158+
selector: ".total"
159+
text: "$"
160+
161+
# Custom predicates
162+
- predicate: "cart_not_empty"
163+
```
164+
165+
### Policy Example
84166

85167
```yaml
86168
# policies/shopping.yaml
87169
rules:
170+
# Allow browsing Amazon
88171
- action: "browser.*"
89172
resource: "https://amazon.com/*"
90173
effect: allow
91174
175+
# Allow checkout with verification
92176
- action: "browser.click"
93177
resource: "*checkout*"
94178
effect: allow
95179
require_verification:
96180
- url_contains: "/checkout"
181+
- element_exists: "#cart-items"
182+
183+
# Block external links
184+
- action: "browser.navigate"
185+
resource: "https://external.com/*"
186+
effect: deny
97187
188+
# Default deny
98189
- action: "*"
99190
resource: "*"
100191
effect: deny

examples/browser_use_checkout.py

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
"""
2+
E-commerce checkout flow with browser-use and predicate-secure.
3+
4+
This example demonstrates:
5+
- Wrapping a browser-use Agent with SecureAgent
6+
- Policy-based authorization for browser actions
7+
- Debug mode for troubleshooting
8+
- Verification predicates for checkout flow
9+
10+
Requirements:
11+
pip install predicate-secure[browser-use]
12+
# Set up your LLM (e.g., OpenAI API key)
13+
"""
14+
15+
import asyncio
16+
import os
17+
18+
# Uncomment to use with actual browser-use
19+
# from browser_use import Agent
20+
# from langchain_openai import ChatOpenAI
21+
22+
from predicate_secure import SecureAgent
23+
24+
25+
def create_shopping_policy() -> str:
26+
"""Create a shopping policy file and return the path."""
27+
policy_content = """
28+
# Shopping policy - controls what the agent can do during checkout
29+
rules:
30+
# Allow browsing and interacting with Amazon
31+
- action: "browser.*"
32+
resource: "https://*.amazon.com/*"
33+
effect: allow
34+
35+
# Allow clicking checkout buttons with verification
36+
- action: "browser.click"
37+
resource: "*checkout*"
38+
effect: allow
39+
require_verification:
40+
- url_contains: "/checkout"
41+
42+
# Allow clicking add-to-cart buttons
43+
- action: "browser.click"
44+
resource: "*add-to-cart*"
45+
effect: allow
46+
47+
# Allow form filling for shipping/payment
48+
- action: "browser.fill"
49+
resource: "*address*"
50+
effect: allow
51+
52+
# Block navigation to external sites
53+
- action: "browser.navigate"
54+
resource: "https://external-site.com/*"
55+
effect: deny
56+
57+
# Default: deny everything else
58+
- action: "*"
59+
resource: "*"
60+
effect: deny
61+
"""
62+
policy_path = "/tmp/shopping_policy.yaml"
63+
with open(policy_path, "w") as f:
64+
f.write(policy_content)
65+
return policy_path
66+
67+
68+
async def run_secure_checkout():
69+
"""Run a secure e-commerce checkout flow."""
70+
71+
# Create policy file
72+
policy_path = create_shopping_policy()
73+
74+
# Example with mock agent (for demonstration)
75+
# In real usage, replace with actual browser-use Agent:
76+
#
77+
# llm = ChatOpenAI(model="gpt-4")
78+
# agent = Agent(
79+
# task="Buy wireless headphones under $50 on Amazon",
80+
# llm=llm,
81+
# )
82+
83+
class MockBrowserUseAgent:
84+
"""Mock agent for demonstration purposes."""
85+
86+
__module__ = "browser_use.agent"
87+
88+
def __init__(self):
89+
self.task = "Buy wireless headphones under $50 on Amazon"
90+
self.llm = "mock_llm"
91+
self.browser = MockBrowser()
92+
93+
async def run(self):
94+
print("Mock agent: Would browse Amazon and add item to cart")
95+
return {"status": "completed", "item": "Sony WH-1000XM4"}
96+
97+
class MockBrowser:
98+
"""Mock browser session."""
99+
100+
pass
101+
102+
# Create mock agent
103+
agent = MockBrowserUseAgent()
104+
105+
# Wrap with SecureAgent for authorization + verification
106+
secure_agent = SecureAgent(
107+
agent=agent,
108+
policy=policy_path,
109+
mode="debug", # Enable debug output
110+
trace_format="console",
111+
principal_id="shopping-agent:checkout",
112+
)
113+
114+
print(f"Created: {secure_agent}")
115+
print(f"Framework: {secure_agent.framework}")
116+
print(f"Policy: {policy_path}")
117+
print()
118+
119+
# Manual step tracing (for demonstration)
120+
step = secure_agent.trace_step("navigate", "https://amazon.com")
121+
secure_agent.trace_step_end(step, success=True)
122+
123+
step = secure_agent.trace_step("search", "wireless headphones")
124+
secure_agent.trace_step_end(step, success=True)
125+
126+
step = secure_agent.trace_step("click", "add-to-cart-button")
127+
secure_agent.trace_snapshot_diff(
128+
before={"cart_count": 0},
129+
after={"cart_count": 1},
130+
label="Cart Update",
131+
)
132+
secure_agent.trace_step_end(step, success=True)
133+
134+
secure_agent.trace_verification(
135+
predicate="cart_not_empty",
136+
passed=True,
137+
message="Cart has 1 item",
138+
)
139+
140+
print("\nCheckout flow traced successfully!")
141+
print("In production, use secure_agent.run() to execute the full flow.")
142+
143+
144+
def main():
145+
"""Main entry point."""
146+
print("=" * 60)
147+
print("E-commerce Checkout with predicate-secure")
148+
print("=" * 60)
149+
print()
150+
151+
asyncio.run(run_secure_checkout())
152+
153+
154+
if __name__ == "__main__":
155+
main()

0 commit comments

Comments
 (0)