From eaf2aae480d603f90e1487ec6f222ffc17d88c20 Mon Sep 17 00:00:00 2001 From: Adam Moussa Date: Thu, 11 Jun 2026 11:58:11 -0400 Subject: [PATCH] Resolve open decisions: per-user auth pattern + reasoning model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fold Adam's decisions and deep-research (wf_1bf9e142) outcomes into the plan: - D4: ES/Apex actions + Per-User OAuth Browser Flow External Credential -> Cognito; native remote-MCP connector off the per-user hop (Beta, per-user binding unconfirmed). - D5: AWS-Hosted Claude as the planner; BYOLLM ruled out (custom-action-only, routes through SF Models API/Trust Layer). Guardrail moves to the MCP/action layer (revises D11). - D1 accepted; D3 accepted; G8 corpus authoring deferred (fund when needed). - Resolve gaps G1/G2/G6; add §0.1 resolutions and a Phase-0 verify-in-org gate. --- docs/agentforce-plan.md | 70 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 6 deletions(-) diff --git a/docs/agentforce-plan.md b/docs/agentforce-plan.md index dc6d181..a270f93 100644 --- a/docs/agentforce-plan.md +++ b/docs/agentforce-plan.md @@ -28,7 +28,9 @@ single hardest reconciliation is **per-user identity**: Agentforce's native remo 2026) and authenticates connectors through **Named/External Credentials**, whose **Per User** OAuth identity type exists at the platform level but is **not yet confirmed for the MCP connector** — if a connector can only bind a **Named Principal** (one service identity), our per-user JWT, ABAC Gmail isolation, and trifecta guarantees break. -That is the controlling risk of this migration (Gap G1, §5) and it drives the surface-integration recommendation. +That was the controlling risk of this migration (Gap G1, §5). **RESOLVED 2026-06-11 (§0.1):** we take the GA +External Service/Apex action path with a Per-User OAuth Browser Flow credential and keep the native MCP connector +off the per-user hop, so the risk is mitigated rather than load-bearing. **Decision log (committed picks — 1 line + rationale + citation):** @@ -37,8 +39,8 @@ That is the controlling risk of this migration (Gap G1, §5) and it drives the s | D1 | **3 agents**: Seahaven Ops, Seahaven Finance, Lauren Exec | 1:1 with trust tiers + Google groups; UX-layer trifecta separation | design.md §12, §3 | | D2 | Deploy as **Agentforce Employee Agents in Slack** | Slack is our surface; only Employee Agents deploy to Slack | `FACT` slack.com/help 36218109305875 | | D3 | **Refine design.md §12**: remove `finance:read` from Lauren Exec; finance lookups go through the Finance agent | Gmail-read + finance-read + a write/egress tool in one session is the exfiltration trifecta | design.md §2.5, §3 (trifecta); §5 | -| D4 | Reach MCP servers via a **Per-User External Credential (OAuth 2.1 Browser Flow → Cognito)**, wrapped as **Apex/External Service actions** until native per-user MCP auth is GA | Preserves real-user `sub` in the JWT; native MCP connector per-user binding unconfirmed in Beta | `FACT` Named Credentials OAuth dev guide; Gap G1/G2 §5 | -| D5 | Agent reasoning model = **Anthropic Claude on Amazon Bedrock**, via **BYOLLM** if it can serve as the Atlas planner, else the **AWS-Hosted Claude Sonnet 4** option | Retains our Claude lineage (legacy Sonnet 4.5/4.6) + Trust Layer; BYOLLM = 30% fewer Einstein Requests | `FACT` developer.salesforce.com supported-models; Agentforce 360 for AWS; Gap G6 §5 | +| D4 | **RESOLVED (2026-06-11, §0.1):** reach MCP tools via **GA External Service (OpenAPI) actions** (or Apex `@InvocableMethod`) authenticated by a **Per-User OAuth 2.1 Browser Flow External Credential → Cognito**. Native remote-MCP connector is NOT used for the per-user hop. | Per-user OAuth is GA; native custom-MCP per-user binding is unconfirmed and documented per-user identity exists only for SF-**hosted** MCP. Trade-off: lose the MCP transport on the Agentforce→tool hop (tools re-exposed as OpenAPI/Apex). | `FACT` research wf_1bf9e142; Named Credentials OAuth dev guide; G1/G2 §5 | +| D5 | **RESOLVED (2026-06-11, §0.1):** agent reasoning/planner model = **AWS-Hosted Claude (Salesforce-managed, on Bedrock)**. **BYOLLM is NOT used for the planner.** | BYOLLM is documented only for custom actions, never as a planner option, and routes back through Salesforce's Models API/Trust Layer anyway. AWS-Hosted is the only documented way to keep Claude as planner. | `FACT` research wf_1bf9e142; developer.salesforce.com supported-models | | D6 | KB → **Agentforce Data Library (unstructured) on Data Cloud**, replacing Bedrock KB `LSDCNHTH6O` + AOSS | Data Libraries auto-create a Data Cloud search index + retriever; managed RAG | `FACT` Trailhead/Atrium Data Libraries; design.md §3 | | D7 | **Retire** `po-sync` / `workorder-sync` KB feeds; structured WO/PO/payments stay **live MCP lookup tools** | Data Libraries are unstructured-only; structured data belongs in DDB-backed MCP tools | `FACT` Data Libraries unstructured-only; design.md §3 | | D8 | Proactive jobs (`fetch-classify`, `daily-digest`, `reminder`, `notion-sync`) **stay as our scheduled Lambdas**, not Agentforce; HIGH-priority alerts continue as **Slack DMs** | No conversational equivalent; keeps Haiku classifier in our Bedrock account; cheapest reliable path | design.md §5; §1f below | @@ -58,6 +60,40 @@ medium**, **3 low**. --- +## 0.1 Decision resolutions — 2026-06-11 (Adam + deep-research wf_1bf9e142) + +All five §6 open decisions are now resolved. Research = a 6-angle, 23-source, 25-claim adversarially-verified +deep-research pass (25/25 confirmed); primary Salesforce/AWS/Anthropic sourcing. Findings supersede the +provisional D4/D5 wording above and the open items in §6. + +| §6 item | Resolution | Basis | +|---------|-----------|-------| +| 1. Surface + licensing | **ACCEPTED** — Agentforce Employee Agents in Slack; Agentforce + Data Cloud licensing accepted. | Adam, 2026-06-11 | +| 2. Reasoning model | **AWS-Hosted Claude (SF-managed)** as the planner. BYOLLM ruled out for the planner (only Salesforce Default / AWS-Hosted drive the Atlas reasoning engine; BYOLLM is custom-action-only and still routes through SF's Models API/Trust Layer). | research wf_1bf9e142 (Q2) | +| 3. Strip finance from Lauren (D3) | **ACCEPTED.** | Adam, 2026-06-11 | +| 4. Per-user auth path (D4) | **External Service (OpenAPI) / Apex actions + Per-User OAuth Browser Flow External Credential → Cognito.** Native remote-MCP connector is Beta and its per-user binding is unconfirmed — do NOT depend on it for the per-user hop. | research wf_1bf9e142 (Q1) | +| 5. Fund SA8000/handbook corpus (G8) | **DEFERRED — fund when needed** (not now). SA8000/compliance + HR agents stay blocked until content is authored; the agents must decline rather than hallucinate in the interim. | Adam, 2026-06-11 | + +**Two consequences that ripple into the design (must be honored downstream):** + +1. **The Agentforce→tool hop is NOT MCP.** Because per-user identity is only achievable on the GA External + Service/Apex action path (not the Beta MCP connector), Agentforce reaches our tools through an **OpenAPI/Apex + facade in front of each MCP server**, authenticated per-user to Cognito. The `sh-mcp-ops`/`-finance` servers, + their JWT validation, scopes, audience-binding, and PII redaction are **unchanged** — only the Agentforce-side + transport changes from MCP to OpenAPI/Apex actions. (Other MCP clients can still speak MCP to the same servers.) + Browser Flow requires an interactive first-auth per user (fine for Slack users; the proactive Lambdas in §1f + are unaffected — they use offline creds). +2. **Our Bedrock guardrail cannot sit on the planner path.** Both AWS-Hosted and BYOLLM keep Salesforce in the + inference path, so keeping inference + our own guardrail in account `328440206208` is **unsatisfiable on the + planner path today**. The Einstein **Trust Layer** covers planner-path moderation; **our guardrail + PII + redaction move entirely to the MCP/action layer** (already the plan for PII — design.md §2.5). This **revises + D11**: the guardrail is applied at the MCP/action layer, not "on the BYOLLM model path." + +**Dropped claim:** the "BYOLLM = ~30% fewer Einstein Requests" figure was **not corroborated** by any verified +source — removed from cost modeling. + +--- + ## 1. Platform-level design ### 1a. Agent roster — how many, and why @@ -434,12 +470,12 @@ Severity: **C**ritical / **M**edium / **L**ow. "Verify" = check against current | # | Gap | Sev | Impact | Workaround / status | Verify | |---|-----|-----|--------|---------------------|--------| -| **G1** | **Per-user OAuth on the MCP connector unconfirmed.** Agentforce MCP connectors authenticate via Named/External Credentials. The platform **Per User** identity type (OAuth 2.1 Browser Flow) exists, but it's not documented that an MCP *connector* can bind **Per User** vs only a **Named Principal**. | **C** | If only Named Principal: all tool calls share one service identity → breaks per-user `sub`, ABAC Gmail isolation, and the trifecta guarantees. | **D4:** wrap MCP tools as **Apex / External Service actions** using a **Per-User External Credential (OAuth Browser Flow → Cognito)** — GA, gives the real-user JWT. Use native MCP connector only once per-user binding is confirmed. | SF MCP guide + Named Credentials release notes; test a Per-User external credential end-to-end | -| **G2** | **Custom remote MCP client is Beta** (Pilot Jul 2025 → Beta Jan 2026). Salesforce-*hosted* MCP is GA (Apr 2026) but that's SF-hosted, not our remote servers. | **C** | Schedule/stability risk for the native-MCP path. | Same Apex/External-Services fallback (GA) as G1 covers it; or wait for remote-MCP GA. | SF release notes for remote-MCP GA date | +| **G1** | **RESOLVED 2026-06-11 (research wf_1bf9e142).** Per-user OAuth Browser Flow on the **native custom remote-MCP connector is unconfirmed**; documented per-user identity exists only for SF-**hosted** MCP. | **C→ mitigated** | If we'd relied on the MCP connector and it bound only a Named Principal: per-user `sub`, ABAC Gmail isolation, and trifecta all break. | **Decided (D4):** do NOT use the native MCP connector for the per-user hop. Use **GA External Service (OpenAPI)/Apex actions + Per-User OAuth Browser Flow External Credential → Cognito** (per-user OAuth is GA, ships in `UserExternalCredential`). | In-org: build one ES action on a Per-User Browser Flow cred → confirm first-call consent, real `sub` reaches the server, and token auto-refresh (§6 verify list) | +| **G2** | **RESOLVED 2026-06-11.** Custom remote MCP client is **Beta** (Pilot Jul 2025 → Beta Jan 2026); SF-*hosted* MCP is GA (Apr 2026) but that's not our remote servers. | **C→ avoided** | Schedule/stability risk on the native-MCP path. | **Avoided by D4** — the GA ES/Apex action path is the per-user transport; the Beta MCP connector is off the critical path. Revisit native MCP once remote-MCP per-user binding reaches GA. | SF release notes for remote-MCP GA date | | **G3** | **Trust Layer masking may over-mask.** Agentforce Trust Layer can mask PII; legacy Alex **deliberately left vendor names/contacts unmasked** (lookup is the bot's job). | M | Vendor lookups could be degraded if Trust Layer masks names. | Configure Trust Layer masking to exclude names/contacts; keep MCP-layer redaction authoritative for bank/routing/card/SSN (design.md §2.5). | Trust Layer data-masking config | | **G4** | **Loss of free-text search over WO comments** (old KB feature) — Data Libraries are unstructured-only, WO/PO are structured MCP lookups. | L | Can't fuzzy-search WO comment text. | Lookup-by-id via MCP tools; or a dedicated retriever over a comment text export if demand appears. | — | | **G5** | **Embedding model not selectable** — Data Cloud uses Salesforce-managed embeddings (vs legacy Titan Embed V2 1024-dim). | L | Less control over retrieval tuning. | Accept managed embeddings; tune chunking. | Data Cloud index config options | -| **G6** | **BYOLLM-as-Atlas-planner unconfirmed.** AWS-Hosted Claude Sonnet 4 is confirmed to power Atlas; whether a **BYOLLM** Bedrock endpoint can be the agent *reasoning* model (not just prompt templates/Models API) is unclear. | M | May not get our-account Bedrock + our guardrail on the planner path. | Fall back to **AWS-Hosted Claude Sonnet 4** managed option (same family). | supported-models doc; test BYOLLM as agent model in Setup | +| **G6** | **RESOLVED 2026-06-11 (research wf_1bf9e142): BYOLLM cannot drive the planner.** Only Salesforce Default / AWS-Hosted options drive the Atlas reasoning engine; BYOLLM is custom-action-only and still routes through SF's Models API/Trust Layer. | M→ resolved | Our-account inference + our guardrail are **unsatisfiable on the planner path**. | **Decided (D5):** use **AWS-Hosted Claude** as the planner; move our guardrail + PII redaction to the **MCP/action layer** (revises D11); rely on the Trust Layer for planner-path moderation. Note AWS-Hosted model is drifting Sonnet 4 → 4.6/Haiku 4.5 (May 2026). | In-org: confirm the reasoning-model selector offers only Default/AWS-Hosted; confirm current AWS-Hosted model name | | **G7** | **Amazon/AMOC corpus is stale** ("migrated from BookStack, may need updating") and access-restricted (AMOC comms = Adam & Robert only). | M | Agent could give outdated Amazon-site guidance. | Audience-restrict the AMOC topic; flag content as stale; re-author before exposing widely. | Notion *AMOC* `33a2ecdd…8162` currency | | **G8** | **SA8000 docs + employee handbook + company policies missing** from Notion (referenced as KB inputs, not found). | M | SA8000/compliance + HR Q&A **blocked**. | **Blocked pending content authoring** — author, stage in S3/Drive, ingest into Ops Knowledge Data Library; until then the agent must decline (without suppressing legitimate misconduct questions). | design.md corpus notes; locate any S3/Drive originals | | **G9** | **Agentforce + Data Cloud licensing / Einstein-Request consumption.** | M | Cost; BYOLLM cuts ~30% of Einstein Requests but Data Cloud + Agentforce licensing still applies. | Budget; BYOLLM to reduce request spend. | Salesforce contract / Einstein Request limits | @@ -454,6 +490,13 @@ sources (§Sources). The **specific** per-user binding for MCP connectors is the ## 6. Open decisions for Adam (with recommendation) +> **STATUS — all resolved 2026-06-11. See §0.1 for the committed resolutions and basis.** Summary: (1) surface + +> licensing **accepted**; (2) reasoning model = **AWS-Hosted Claude** (BYOLLM ruled out for the planner); +> (3) **D3 accepted** (finance stripped from Lauren Exec); (4) per-user auth = **ES/Apex actions + Per-User +> Browser Flow → Cognito** (native MCP connector off the per-user path); (5) corpus authoring (G8) **deferred — +> fund when needed**. The hands-on verify-in-org tests below remain the build-time gate for #2 and #4. Original +> recommendations retained for the record: + 1. **Surface + licensing.** Confirm **Agentforce Employee Agents in Slack** as the surface and accept Agentforce + Data Cloud licensing/Einstein-Request cost (G9). *Recommend: yes* — Slack is already our hub and only Employee Agents deploy there; it gives the multi-agent trust-tier mapping design.md §12 wants. @@ -474,6 +517,21 @@ sources (§Sources). The **specific** per-user binding for MCP connectors is the Lower-stakes confirmations: new `sh-agentforce` repo (D9, recommend yes); identity provisioning from Google Groups to reconcile the two control planes (G11, recommend SCIM). +**Verify-in-org gate (do these spikes in Phase 0 before building on the decisions — from research wf_1bf9e142):** +1. **(Auth, highest priority)** Build one **External Service (OpenAPI) action** on a **Per-User OAuth Browser + Flow External Credential** pointed at Cognito; invoke it from an Agentforce agent **running in Slack** and + confirm: (a) the end user gets the interactive "Allow Access" consent on first call, (b) the per-user token + (`UserExternalCredential`) is sent so the tool server sees the real `sub`, (c) token auto-refresh works. + Slack-side consent UX is undocumented in verified sources — observe it directly. +2. **(Auth, native path check)** Register a test custom remote MCP server and inspect the auto-generated + External Credential — confirm whether its identity type can be set to **Per-User Browser Flow** vs only + **Named Principal**. If Per-User is offered, native MCP becomes a future option; until then D4 (ES/Apex) stands. +3. **(Auth, limits)** Confirm headless/automated invocation behavior (Browser Flow needs interactive first-auth + per user), per-org limits on number of ES/Apex actions, and added latency vs native MCP. +4. **(Model)** Confirm the reasoning-engine selector (Setup → Agentforce Agents; `model_config` in Agent Script) + offers only **Salesforce Default** / **AWS-Hosted**, and confirm the current model name behind AWS-Hosted + (Sonnet 4 vs 4.6 vs Haiku 4.5). + --- ## Sources (platform claims verified via web search, 2026-06-11)