feat(examples): add Azure AI Foundry + LangGraph example#132
feat(examples): add Azure AI Foundry + LangGraph example#132abhinav-galileo wants to merge 12 commits into
Conversation
Customer support agent deployed on Azure AI Foundry Hosted Agents, governed by Agent Control at runtime. Demonstrates step-specific controls (pre/post), runtime toggle from the UI, and defense-in-depth across tool and LLM boundaries.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
- Replace hardcoded Agent Control server IP with ${AGENT_CONTROL_URL}
env var placeholder in agent.yaml
- Remove pyproject.toml since requirements.txt is sufficient for this
flat example (used by both Dockerfile and local setup)
- Rewrite deploy section with actual step-by-step azd commands - Add section for deploying to existing Foundry project - Add Agent Control VM deployment instructions - Document gotchas (pip upgrade, .dockerignore, DB reset, policy refresh) - Add .dockerignore to exclude .venv from container builds - Add azd infra (Bicep templates from azd-ai-starter-basic) - Add azure.yaml service definition - Fix local_test.py to use new simplified tool API - Add load_dotenv() to entry scripts for .env support
…y example - Eliminate module-level shared state in graph.py that raced under concurrent requests; pass messages as params, return response directly - Use ainvoke() instead of sync invoke() to avoid blocking the event loop - Switch tools.py to checked-wrapper pattern so @control() sees .name at registration time and correctly classifies steps as type="tool" - Fix seed_controls.py 409 handler to filter by name and handle missing controls instead of raising StopIteration on paginated results - Align .env.example model name with agent.yaml and settings.py - Add AGENT_CONTROL_API_KEY to agent.yaml environment variables - Remove duplicate env var resolution in model.py - Add example to examples/README.md index table
…resh - Add DEMO_SCRIPT.md with step-by-step walkthrough - Switch control execution from server to sdk (lower latency) - Reduce policy refresh interval from 5s to 2s for snappier demos - Link demo script from README
Leak, block, toggle. Removed repetitive per-control walkthrough.
…s, JS-safe regex - Add 5th control (block-pii-in-response) on llm_call post for defense in depth - catches PII in LLM output even if tool leaked it earlier - Add explicit step_types (llm/tool) to all control scopes - Replace (?i) with [Xx] case alternation for JS regex compatibility in the Agent Control UI
- Add SSN to customer PII mock data
- Replace block-customer-pii + block-pii-in-response with single
block-pii control targeting both lookup_customer_pii and llm_call
- Simpler regex (\d{3}-\d{2}-\d{4}) everyone recognizes
- Update demo script to focus on SSN flow
- Add process_refund tool with @control() - Add max-refund-amount control using JSON evaluator with field_constraints (refund_amount max: 100) instead of regex - proper numeric comparison - Merge lookup_customer tools into single tool with SSN - Simplify to single customer (Jane Doe), single order (ORD-1001) - Update demo script with two flows: PII protection + refund limits
…ompat The JSON evaluator needs valid JSON input. The @control() decorator stringifies dict output with Python repr (single quotes), which breaks JSON parsing. Returning json.dumps() from the tool ensures the evaluator can parse the refund_amount field for numeric constraint checking. Also fix stray text in seed_controls.py from clipboard paste.
- Use selector path "output" with field "refund_amount" instead of path "*" with "output.refund_amount". The wildcard path returns the full Step dump where output may be a string (in Foundry hosted env), causing the JSON evaluator to fail navigating nested fields. - Expand mock orders to 10 (ORD-1001 through ORD-1010) - Remove debug logging from tools.py
- Use exact prompts that work in Foundry playground - Emphasize starting new chat for each step (avoids conversation memory replaying old tool calls) - Add evaluator type column to controls reference
|
Since the PR was opened, Microsoft has retired the initial-preview Hosted Agents backend used by azure-ai-agentserver-langgraph. Updating this contribution would therefore require migrating the example to the current responses/invocations hosting protocols rather than a straightforward rebase. I’m closing this implementation because its underlying platform contract is no longer current. The use case remains valuable, and we would welcome a future version built against the latest Foundry APIs, with authorization for side-effecting operations performed before execution. Migration guidance: https://learn.microsoft.com/en-us/azure/foundry/agents/how-to/migrate-hosted-agent-preview |
Summary
examples/azure_foundry_langgraph/demonstrating Agent Control governing a LangGraph agent deployed on Azure AI Foundry Hosted Agents@control()Demo flow
Test plan
python seed_controls.pycreates controls on a running Agent Control serverpython local_test.pypasses against a local serverazd deploybuilds and deploys to Azure AI Foundry Hosted Agents