客户360助手

Customer 360 Assistant 是一个基于 Microsoft Teams、Microsoft Foundry 和 Azure API Management 构建的开源参考实现,用户可直接在 Teams 中提问,由单个 Foundry 代理将请求路由到 Salesforce、ServiceNow 等系统并调用对应工具,所有操作都以当前登录用户的身份和权限执行,适用场景包括客户经理在会议前获取客户 360 视图、会中或会后在 CRM 中更新记录等。

  • by ozgurkarahan
  • Python
  • 本地部署
  • 4 星标
  • 更新于
在 GitHub 查看 ozgurkarahan/salesforce-meta-tool-identity-propagation

使用说明

Build the engagement layer once. Let one agent act across all your systems of record.

Customer 360 Assistant is an open-source reference implementation built on Microsoft Teams, Microsoft Foundry and Azure API Management. People ask in Teams. One Foundry agent routes each request to the right tool. In this sample that means Salesforce and ServiceNow; Jira, SAP, Workday or your own APIs follow the same pattern. Every action runs as the signed-in user, with their own permissions in each system.

▶ Watch the 2:40 story · Project page · Deploy it · Read the architecture story

See It in Action (2:40)

Alice, an account manager, has five minutes before a call with Contoso. In a Teams group chat she gets a 360° view across Salesforce and ServiceNow. After the call, she updates the CRM in one sentence. Every action runs as Alice.

https://github.com/user-attachments/assets/82847835-87b0-42e4-9bb8-fa39cc140551

Animated mock-ups with demo data (Contoso, Alice, Bob). Source and render instructions: video/. Consent is designed to happen once per system; a current Foundry platform issue can ask users to consent again after about an hour (known issue).

One Agent Between Your People and Your Systems

Layer You build it What it does
Engagement layer Once Teams 1:1 and group chats, Microsoft 365 Copilot through Foundry publishing, and a web chat. People stay in the tools they already use.
One agent Once A Microsoft Foundry agent understands the request, picks the tools, correlates answers across systems and drafts the update.
Identity gateway and tools Once per system of record Each system gets a tool server behind Azure API Management. The gateway swaps the user's sign-in for that same user's token in the system.

The thread through every layer is the user's identity. People sign in once with Microsoft Entra ID, and every tool call carries that identity.

Why It Matters

  • Meets people where they work. The assistant lives in Teams chats and, through Foundry publishing, in Microsoft 365 Copilot. There is no new portal to learn.
  • One agent, many systems. Adding a system of record means adding a tool server, a gateway policy and a connection. The agent and the Teams experience stay the same.
  • Acts as the user, never as a super-user. Operations in each system run with the user's own token, so Salesforce sharing rules, field-level security and ServiceNow ACLs apply exactly as they do today.
  • Accountable by design. Writes show the real person in native audit fields such as Last Modified By, and each per-user token exchange appears in Salesforce Login History.
  • Broad reach, small toolset. Seven generic tools let the agent discover, at runtime, the objects and fields the user can see, standard and custom alike. A new custom object needs no new code.
  • Open standards, automated deployment. MCP, OAuth 2.0 and OpenID Connect, with a documented path to other identity providers such as Okta or PingFederate. Bicep and azd deploy the stack once the prerequisites are in place.

What People Ask

Moment Ask the assistant Systems
Before a customer call "Prepare me for my QBR with Acme Corp. Pull everything from both systems." Salesforce + ServiceNow
Account review "Give me a Customer 360 view for Contoso Ltd." Salesforce + ServiceNow
Incident triage "We have a P1 incident about API gateway failures. Which accounts and open opportunities are affected?" ServiceNow → Salesforce
Change planning "We're planning a billing upgrade on Saturday. Check the change request and the accounts with upcoming renewals." ServiceNow → Salesforce
After the call "Add a note on the Contoso Analytics Add-on opportunity: the customer wants a POC first. Move the close date to next quarter." Salesforce (write, as the user)

Adapted from docs/TEST_PROMPTS_360.md, which run against seeded demo data. Every prompt runs with the asker's own access; the last one is the CRM update shown in the video.

Acts as the User, Never as a Super-User

  1. Sign in once. Alice signs in to Teams with her work account (Microsoft Entra ID).
  2. Consent once per system, by design. Standard OAuth consent happens the first time the agent reaches a system; a known platform issue can ask again after about an hour.
  3. The gateway swaps the token. Azure API Management validates Alice's token, finds her account in each system, and gets a token issued to Alice.
  4. Each system applies its own rules. Sharing rules, field-level security and ACLs decide what Alice can see and change.
  5. Writes carry her name. The record shows Last modified by: Alice, not an integration user.

No shared credential touches business data. A minimal-access service account only maps Alice to her Salesforce user. Identity propagation stops privilege escalation, but it cannot stop an agent from misreading intent, so keep confirmations for destructive actions (what it does not protect against).

Built to Grow: Plug In Your Next System

Salesforce and ServiceNow are working examples. Every system follows the same three-part pattern:

  • a tool server that discovers, queries and acts on the system,
  • a gateway policy that exchanges the user's token for a token in that system,
  • a Foundry connection that attaches the tools to the agent.

Jira, SAP, Workday and your own APIs are not included in this repository; they are where the pattern goes next.

Why meta-tools instead of one tool per object? Many MCP servers define one tool per object, so every new object means new code and a longer tool list. A meta-tool server works like a shell: the agent discovers objects, learns their fields and builds the query itself, with the user's own access. The tool list stays the same whatever the size of the org. See the meta-tool pattern.

What's in the Box

In this repository

  • Salesforce meta-tool server: 7 tools (whoami, list_objects, describe_object, soql_query, search_records, write_record, process_approval) on Azure Container Apps.
  • Identity gateway: Azure API Management policies for the three-phase on-behalf-of (OBO) exchange.
  • Foundry agents: salesforce-assistant and customer360-assistant, wired through OAuth2 identity-passthrough connections. Their behaviour comes from six versioned Foundry skills (salesforce-crm, servicenow-itsm, customer360-correlation, revenue-at-risk, meeting-prep, change-risk), with a lean system prompt on top.
  • Engagement: a web chat app (MSAL.js), a Teams app published to your org catalog, and Microsoft 365 Copilot through Foundry publishing.
  • Delivery: Bicep and azd, Salesforce org setup scripts, demo-data seeding and E2E tests.

The two-repo Customer 360 demo adds snow-meta-tool (ServiceNow tools, same pattern) and correlated demo data (setup).

[!NOTE] This is a reference implementation with demo data, not an audited production product. Read the current scope and limitations and the known platform issues before you adapt it.


For Architects and Developers

The rest of this page is the technical path: architecture, identity flow, tools and deployment.

Architecture

draw.io source

How It Works

The user asks a question. The agent discovers objects, learns schemas, and queries Salesforce — all through the same seven tools, all with the user's own identity.

Excalidraw source

On-Behalf-Of (OBO) Token Exchange

APIM handles a three-phase exchange: validate the Azure AD JWT, resolve the Salesforce username, and acquire a per-user Salesforce token. The MCP server never sees Azure AD credentials. Foundry obtains the user's delegated token through an OAuth2 identity-passthrough connection against a customer-owned Entra app (one-time consent per user) — Agent Service no longer forwards Microsoft-audience tokens to custom MCP endpoints.

Deep dive: Detailed OBO exchange animation | Full detail PNG | Excalidraw source

v2 (2026-07): OAuth2 identity passthrough. Foundry Agent Service blocks Microsoft-audience tokens to custom MCP endpoints (Cannot pass Microsoft token to untrusted MCP endpoint), which ended the original UserEntraToken connection. v2 uses an OAuth2 identity-passthrough connection backed by your own Entra app: one-time consent per user, same three-phase OBO exchange. Rationale and migration: CHANGELOG.md.

The 7 Tools

Tool What it does
whoami Resolve the current user's identity from the bearer token
list_objects Discover objects (1000+ in a typical org), filter by name/label
describe_object Field schemas, types, required flags, picklists, external IDs
soql_query Full SOQL: relationships, aggregates, GROUP BY, auto-pagination
search_records SOSL full-text search across multiple objects simultaneously
write_record Create, update, upsert (by external ID), delete
process_approval Submit, approve, reject via Salesforce approval workflows

The seven tool definitions come to roughly 1.65K tokens per model call (about 2.1K with the server instructions), whatever the size of the org. Measured from the server's tools/list with the o200k_base tokenizer (October 2026); details in docs/deepdive.md. Field schemas are loaded on demand through describe_object rather than pre-loaded into the system prompt.

Skills and Publishing (v3)

  • Skills: each skills/<name>/SKILL.md becomes a Foundry skill version. azd up uploads a new version only when the content changes, and the agents pin exact versions. Prompt agents can't load skills at runtime yet, so the hook compiles the pinned versions into the instructions (SKILLS_MODE=inline). SKILLS_MODE=native is ready for when the GitHub Copilot harness is available. See AGENT.md.
  • One toolbox (opt-in): azd env set C360_TOOLS_MODE toolbox serves Customer 360 from a single Foundry Toolbox that holds both MCP servers and all skills.
  • Staged publish: every agent version gets its own deployment. The hook smoke-tests it before it receives Teams traffic, and python hooks/postprovision.py --rollback restores the previous version.
  • E2E: python scripts/test_e2e_customer360.py [--path version|app] runs one or more turns per skill plus a write guard.

Deep Dive

For detailed technical explanations, see docs/deepdive.md:

Deployment and Setup

New to this project? Follow the step-by-step installation guide for a complete walkthrough from a clean Azure subscription and Salesforce org.

Prerequisites

You need an Azure subscription (Contributor + User Access Administrator), a Salesforce Developer or Sandbox org, and the Azure Developer CLI, Azure CLI, Python 3.11+, Docker Desktop, the Salesforce CLI and OpenSSL. Versions and links are in Phase 0 of the installation guide.

Quick Deploy

If you already have a configured Salesforce org and certificate:

git clone https://github.com/ozgurkarahan/salesforce-meta-tool-identity-propagation.git
cd salesforce-meta-tool-identity-propagation
pip install -r requirements.txt

azd env new obo
azd env set SF_INSTANCE_URL "https://your-org.my.salesforce.com"
azd env set SF_CONNECTED_APP_CLIENT_ID "<connected-app-consumer-key>"
azd env set SF_SERVICE_ACCOUNT_USERNAME "<svc@your-org.my.salesforce.com>"

# v2: Entra app backing the OAuth2 identity-passthrough connection
# (create it first -- see docs/installation.md Phase 3)
azd env set MCP_OAUTH_CLIENT_ID "<mcp-oauth-app-id>"
azd env set MCP_OAUTH_CLIENT_SECRET "<mcp-oauth-app-secret>"

azd up

The postprovision hook automatically uploads certs/sf-jwt-bearer.pfx to Key Vault, creates the APIM certificate binding, and sets SF_JWT_BEARER_CERT_THUMBPRINT. No manual thumbprint step needed.

After azd up completes, open the Chat App URL printed at the end. Sign in with your Azure AD account and send a message (e.g., "Show me my Salesforce accounts").

From Scratch

  1. Generate certificate — see installation guide Phase 1
  2. Salesforce setup — see installation guide Phase 2
  3. Set environment variables (5 vars — no thumbprint needed):
    azd env set SF_INSTANCE_URL "https://your-org.my.salesforce.com"
    azd env set SF_CONNECTED_APP_CLIENT_ID "<consumer-key>"
    azd env set SF_SERVICE_ACCOUNT_USERNAME "<svc@your-org.my.salesforce.com>"
    azd env set MCP_OAUTH_CLIENT_ID "<mcp-oauth-app-id>"       # v2 -- see installation guide Phase 3
    azd env set MCP_OAUTH_CLIENT_SECRET "<mcp-oauth-app-secret>"
    
  4. Deploy: azd up
  5. Map user identities — see installation guide Phase 4

Environment Variables

The full table moved to the installation guide: Reference: Environment Variables.

Project Structure

The annotated tree moved to the installation guide: Reference: Project Structure.

Common Issues

Troubleshooting moved to the installation guide: Common Issues. That section also covers the v2 consent and token-expiry issues.


Related Projects

This repository is part of the Identity Propagation series on end-to-end user identity for AI agents: no shared service account reading or writing business data, and every action traceable to a real user. Read the story: From Theory to Production: Salesforce Meta-Tool & Identity Propagation.

  • snow-meta-tool — The ServiceNow counterpart: the same meta-tool pattern and OBO identity propagation, applied to ServiceNow ITSM. Deploy both side by side to power the Customer 360 Foundry agent, which correlates Salesforce CRM data with ServiceNow incidents, changes and requests under the user's own identity in each system.
  • propagate-id-entra — An Entra ID identity-flow proof of concept in the same series.

Contributing

Contributions are welcome. Please open an issue or submit a pull request.

This project uses azd for deployment. See Deployment and Setup to get a local environment running.


License

MIT License


Related article: The Meta-Tool Pattern Applied to Enterprise on LinkedIn.