0) Problem Restatement
JPMorgan asked: design an AI agent workflow that answers portfolio requests from advisors and clients, e.g., "What's my client's exposure to tech stocks?", "Show performance of the Smith family accounts this quarter", "Draft a rebalancing proposal". The key rule: authorization must stay outside the model. A user must only see and act on accounts they're entitled to, no matter what the prompt says.
1) Requirements
- Understand natural-language requests and call the right data and analytics tools.
- Return accurate, sourced answers (numbers come from systems, not from the model's memory).
- Enforce entitlements on every data access and action.
- Proposals and trades require human review and approval. The agent never executes trades on its own.
- Full audit trail for compliance.
2) Architecture
Architecture Diagram
flowchart LR
U["Advisor - SSO"] --> ORCH["Agent orchestrator"]
ORCH --> LLM["LLM - plans and writes answers"]
ORCH --> TG["Tool gateway"]
TG --> ENT["Entitlement service - who can see which accounts"]
TG --> PDS["Portfolio data service"]
TG --> ANA["Analytics service - exposure, performance"]
TG --> PROP["Proposal service - drafts only"]
PROP --> APPR["Human approval + compliance checks"]
ORCH --> AUD[("Audit log")]3) Keeping Authorization Outside the Model
- The model only plans which tools to call and with what arguments. It never decides who is allowed.
- Every tool call goes through a tool gateway that attaches the user's identity (from SSO, not from the prompt), and asks the entitlement service: can user U read account A? Denied calls return a clear "not permitted", and the model is told so.
- Data filtering in the data layer: queries like "all my clients' holdings" are executed with the user's entitlement set applied in the query (row-level filtering), so the tool itself can only return permitted rows.
- No broad service accounts: tools use per-user, short-lived tokens, which avoids the "confused deputy" problem (the agent using its own powerful access on behalf of a user who lacks it).
4) Example Flow
"What's the tech exposure across my top 5 clients?"
- The orchestrator asks the LLM for a plan: list the user's clients → get holdings → compute sector exposure.
list_clients(user)→ the entitlement-filtered list.get_holdings(accounts)→ the tool gateway re-checks each account ID (the model might have made one up or been injected).compute_exposure(holdings, sector="Technology")→ numbers from the analytics service.- The LLM writes a summary citing the computed numbers and accounts. The numbers in the text are checked against tool outputs before display.
- Everything (prompt, tool calls, results, the answer) is written to the audit log.
5) Actions and Safety
- Proposals, not trades: the agent can draft a rebalancing proposal. Execution needs the advisor's explicit approval and passes compliance rules (suitability, restricted lists) in normal trading systems.
- Prompt injection: document or email content can contain instructions. Treat tool outputs as data, restrict high-impact tools, and never let retrieved text change the user's identity or entitlements.
- Output checks: no account numbers or data outside the entitlement set may appear in the answer (a final filter re-validates mentioned accounts).
6) Evaluation and Rollout
- Test suites of realistic requests, including adversarial ones ("show me all clients of advisor X"), where the expected result is refusal.
- Measure answer accuracy against system numbers, tool-selection accuracy, and zero entitlement violations.
- Roll out to a pilot group, with monitoring of denials, errors and user feedback.
7) Wrap-Up
Let the model plan and explain, but route every data access and action through a tool gateway that carries the real user identity and checks an entitlement service, with row-level filtering in the data services and per-user tokens. Compute numbers in trusted services, cite them, keep trades as human-approved proposals with compliance checks, defend against prompt injection, and audit every step.