W-21685788: Expand using-webapp-salesforce-data guidance#101
W-21685788: Expand using-webapp-salesforce-data guidance#101channiganfsu wants to merge 9 commits intoforcedotcom:mainfrom
Conversation
Add detailed reference docs for schema introspection, read query generation, mutation query generation, query testing, and webapp integration patterns. Made-with: Cursor
…ipts/ Relocate the schema search script from the skill root into a dedicated scripts/ directory for better organization. Made-with: Cursor
…rce-data - Add GraphQL Non-Negotiable Rules section (6 critical platform rules) - Fix mutation template to include allOrNone wrapper - Add doc cross-references (schema introspection, query generation, testing, webapp integration) - Add deploying-webapp-to-salesforce skill cross-reference - Update script paths from .a4drules/... to scripts/graphql-search.sh - Expand checklist with allOrNone, pagination, and error handling items - Add two named webapp integration patterns (external .graphql, inline gql) Made-with: Cursor
jodarove
left a comment
There was a problem hiding this comment.
can you also include the changes to the graphql-search.sh from https://github.com/salesforce-experience-platform-emu/webapps/pull/345/changes?
| @@ -0,0 +1,140 @@ | |||
| # Mutation Query Generation | |||
There was a problem hiding this comment.
should the folder name for these be "references" or maybe "assets" instead of "docs"? https://agentskills.io/specification#directory-structure
There was a problem hiding this comment.
good catch, will update to references (I see that in other skills as well)
|
|
||
| 1. **Schema is the single source of truth** — Every entity name, field name, and type must be confirmed via the schema search script before use in a query. Never guess — Salesforce field names are case-sensitive, relationships may be polymorphic, and custom objects use suffixes (`__c`, `__e`). See [Schema Introspection](docs/schema-introspection.md) for entity identification and iterative lookup procedures. | ||
|
|
||
| 2. **`@optional` on all record fields** (read queries) — Salesforce field-level security (FLS) causes queries to fail entirely if the user lacks access to even one field. The `@optional` directive (v65+) tells the server to omit inaccessible fields instead of failing. Apply it to every scalar field, parent relationship, and child relationship. Consuming code must use optional chaining (`?.`) and nullish coalescing (`??`). |
There was a problem hiding this comment.
not related to your pr (let's add it to the back burner): i would love to tweak this, @optional on everything may be too extreme and masks real permission misconfigurations during development, fields critical to business logic (Id, fields used in filtering/routing) should fail loudly, not silently return undefined
There was a problem hiding this comment.
yup, I replied to this in the webapps PR, and also agreed we should tweak it (but in a follow up PR)
| Run the search script from the **SFDX project root** to get all relevant schema info in one step: | ||
|
|
||
| ```bash | ||
| bash .a4drules/skills/using-salesforce-data/graphql-search.sh <EntityName> |
There was a problem hiding this comment.
grr, how'd this get missed?
|
|
||
| The schema reflects the **current org state**. Custom objects and fields appear only after metadata is deployed. | ||
|
|
||
| - **Before** running `npm run graphql:schema`: Deploy all metadata and assign permission sets. Invoke the `deploying-to-salesforce` skill for the full sequence. |
There was a problem hiding this comment.
is this skill valid? the only one i see in the repository is deploying-webapp-to-salesforce
There was a problem hiding this comment.
I guess my search ignored the files in the docs folder, I guess I only updated this in the SKILL.md file
| | Connect REST | `sdk.fetch` | `/services/data/v{ver}/connect/file/upload/config` — file upload config | | ||
| | Einstein LLM | `sdk.fetch` | `/services/data/v{ver}/einstein/llm/prompt/generations` — AI text generation | | ||
|
|
||
| **Not supported:** |
There was a problem hiding this comment.
should we leave this section? it is valid
There was a problem hiding this comment.
I removed it for now, it's a bit of that negative constraint situation. If we say what is supported, an attempt of doing anything else is working outside our guidelines. I don't want to even put the idea in the agents "head" 😄
There was a problem hiding this comment.
based on Claudes defense, I'll revert this for now, and we can examine further later
|
|
||
| Responses follow `uiapi.query.ObjectName.edges[].node`; fields use `{ value }`. | ||
|
|
||
| ## Conditional Field Selection |
There was a problem hiding this comment.
is this section repeated? what's the best place to have it?
There was a problem hiding this comment.
let's put it in the backlog, and try these changes for now.
| --- | ||
| name: using-webapp-salesforce-data | ||
| description: "Salesforce data access for reading, writing, and querying records via REST, GraphQL, Apex, or Platform SDK. Use when the user wants to fetch, search, filter, sort, display, create, update, delete, or attach files to Salesforce records (standard objects like Accounts, Contacts, Opportunities, Cases, Quotes, or any custom object) in a web app or UI component (React, Angular, Vue, etc.); call Chatter, Connect, or Apex REST APIs; or invoke AuraEnabled Apex methods from an external app. Does not apply to authentication/OAuth setup, schema changes (adding fields, relationships), Bulk/Tooling/Metadata API usage, declarative automation (Flows, Process Builder), general LWC/Apex coding guidance without a specific data operation, or Salesforce admin/configuration tasks." | ||
| description: "Salesforce data access for reading, writing, and querying records via REST, GraphQL, Apex, or Platform SDK. Use when the user wants to fetch, search, filter, sort, display, create, update, delete, or attach files to Salesforce records (standard objects like Accounts, Contacts, Opportunities, Cases, Quotes, or any custom object) in a web app or UI component (React, Angular, Vue, etc.); call Chatter, Connect, or Apex REST APIs." |
There was a problem hiding this comment.
we removed the not supported section, claude really likes the "not supported" section, here's what it says:
▎ "...Does not apply to authentication/OAuth setup, schema changes (adding fields, relationships), Bulk/Tooling/Metadata API usage, declarative automation (Flows, Process Builder), general LWC/Apex coding guidance
without a specific data operation, or Salesforce admin/configuration tasks."
The PR truncates the description to end at:
▎ "...call Chatter, Connect, or Apex REST APIs."
Why the exclusions matter: Skills use progressive disclosure — at discovery time, the agent only sees name + description to decide whether to activate a skill. The "Does not apply to..." clause acts as a negative
trigger, telling the agent "don't pick me for these scenarios."
Without it, consider a user saying "add a Industry field to the Account object." That involves schema changes (metadata). With the exclusions, the agent reads "Does not apply to...schema changes (adding fields,
relationships)" and skips this skill, correctly routing to something like generating-custom-field. Without the exclusions, the agent sees "Salesforce data access...Account...web app" and might incorrectly activate
this data-access skill.
The same applies to "set up OAuth for my app" (authentication), "create a Flow that updates Contacts" (declarative automation), or "write an Apex utility class" (general coding without a data operation). These are
all plausible false-positive activations.
In short: positive triggers say "pick me when X," negative triggers say "not me when Y." Both are needed for reliable skill selection, especially in a library with 27+ skills that have overlapping domain
vocabulary.
There was a problem hiding this comment.
fair assessment, and also when considering the scale of skills in this repo
Made-with: Cursor
This reverts commit f439b7a.
jodarove
left a comment
There was a problem hiding this comment.
lgtm! let's include the latest changes to graphql-search.sh from https://github.com/salesforce-experience-platform-emu/webapps/pull/345/changes
jodarove
left a comment
There was a problem hiding this comment.
@channiganfsu see my latest comments
| @@ -1,3 +1,3 @@ | |||
| --- | |||
| name: using-webapp-salesforce-data | |||
| description: "Salesforce data access for reading, writing, and querying records via REST, GraphQL, Apex, or Platform SDK. Use when the user wants to fetch, search, filter, sort, display, create, update, delete, or attach files to Salesforce records (standard objects like Accounts, Contacts, Opportunities, Cases, Quotes, or any custom object) in a web app or UI component (React, Angular, Vue, etc.); call Chatter, Connect, or Apex REST APIs; or invoke AuraEnabled Apex methods from an external app. Does not apply to authentication/OAuth setup, schema changes (adding fields, relationships), Bulk/Tooling/Metadata API usage, declarative automation (Flows, Process Builder), general LWC/Apex coding guidance without a specific data operation, or Salesforce admin/configuration tasks." | |||
There was a problem hiding this comment.
I have played a looot, on seeing when the skill is picked. this description, give us a good chance (see Drew's tool output), now, to be fair, it does not always get picked (it scapes me why); but in afv, now i see it show up a bit; and for sure when: either when asking which skills can we use for the prompt, or by adding a small modification to a rule (check this pr):
| description: "Salesforce data access in web apps (React/Angular/Vue) — GraphQL queries, REST calls, CRUD, and record fetching via the Data SDK. MUST USE when the task involves ANY of: fetching, querying, displaying, loading, showing, pulling, listing, or integrating Salesforce data into a component; GraphQL queries or mutations against Salesforce (write, optimize, debug, fix, or triage); CRUD operations — create/insert, read/get, update, or delete ANY Salesforce record (Account, Contact, Opportunity, Case, Lead, Quote, custom objects, junction objects, many-to-many relationship tables); searching, filtering (by any field — status, owner, email, date, picklist), sorting, or paginating through records; using sdk-data, createDataSDK, gql tag, NodeOfConnection, or GraphQL directives (@optional, @required); calling Connect REST, Apex REST, UI API, or Einstein LLM endpoints via sdk.fetch; fetching current user info or User object data; exploring org schema, querying object metadata, or looking up fields/relationships (e.g., \"what fields are on Case\"); wiring up or adding data fetching to a React/Angular/Vue component; triaging, debugging, or investigating GraphQL issues — empty data, ValidationError, DataFetchingException, missing fields, HTTP 200 with errors, \"fix this query,\" \"why is my query not working.\" Does NOT apply to: LWC (@wire, getRecord, lightning/uiRecordApi, imperative Apex); server-side Apex (triggers, classes, batch jobs); authentication/OAuth; schema changes (adding fields/objects); Bulk/Tooling/Metadata/Composite API; declarative automation (Flows, Process Builder); dashboards or reports (unless fetching underlying data); or conceptual Salesforce explanations without a concrete data-fetching task." |
There was a problem hiding this comment.
The description is outside the bounds of what is considered best practice for skill descriptions. Here is what /skill-creator had to say about it:
Based on the skill-creator's guidance, this description has some strengths but several issues:
What works
- Clear about the skill's domain (Salesforce data access in web apps)
- Includes both positive triggers and explicit exclusions
- Mentions specific technologies and error patterns users might encounter
What doesn't
Way too long. The skill-creator says metadata (name + description) should be ~100 words. This is 250+. Descriptions are always loaded into context, so every token here costs across
every conversation — even when the skill isn't relevant.
Heavy-handed MUSTs and ALL CAPS. The skill-creator specifically flags this as an anti-pattern:
▎ If you find yourself writing ALWAYS or NEVER in all caps, that's a yellow flag — reframe and explain the reasoning so that the model understands why the thing you're asking for is
important.
"MUST USE when the task involves ANY of:" is exactly what the guide warns against.
Exhaustive keyword enumeration feels overfitty. Listing every synonym ("fetching, querying, displaying, loading, showing, pulling, listing, integrating") and every object type
("Account, Contact, Opportunity, Case, Lead, Quote") tries to brute-force triggering rather than conveying the concept. The model understands that "show me accounts" is data fetching —
you don't need to enumerate every verb and noun.
The exclusion list is too detailed for a description. Seven bullet points of negatives belong in the SKILL.md body, not the description.
A tighter alternative
Something like:
▎ Salesforce data access in web apps (React/Angular/Vue) using the Data SDK — GraphQL queries/mutations, REST calls, CRUD operations, record fetching, filtering, and pagination. Use
this skill whenever a component needs to fetch, display, or modify Salesforce records, or when debugging GraphQL issues (empty data, validation errors, broken queries). Also covers
schema exploration and org metadata lookups. Does not apply to LWC wire adapters, server-side Apex, or Salesforce admin/declarative tools.
That's ~70 words, covers the same ground conceptually, and trusts the model to generalize from "fetch, display, or modify" without needing every synonym listed.
There was a problem hiding this comment.
I know the "trusts the model" is what we are having a big problem with right now, but I'd hesitate to want to go with such a large description
| @@ -0,0 +1,221 @@ | |||
| # Webapp Integration | |||
|
|
|||
| ## When to Use | |||
There was a problem hiding this comment.
🫤 , i think we may be asking too much of gpt5. these references were too much during my testings; i have gotten the best results by condensing the references into the skill.md; attached the one i have been using.
References: Contributing guide · Skill authoring guide · Agent Skills spec
What changed
Updated the
using-webapp-salesforce-dataskill to better cover common web app data access workflows with Salesforce. This expands the mainSKILL.md, adds focused supporting docs for schema introspection, read query generation, mutation query generation, query testing, and React webapp integration, and movesgraphql-search.shintoscripts/to match the expected skill layout.Why
The skill needed more complete and actionable guidance for agents building UI-driven Salesforce integrations. This fills gaps around discovering schema, generating safe GraphQL queries and mutations, testing data access patterns, and wiring Salesforce data into web app components while keeping the core skill concise and moving detailed guidance into supporting docs.
Notes
The update also incorporates prior PR feedback by tightening wording, improving formatting, and aligning the skill more closely with the companion
using-salesforce-dataguidance. I did not run additional automated validation locally during PR creation, so CI should be the source of truth for the skill structure and spec checks.Skills
Manual checklist
Description quality
Instructions
Context efficiency
templates/,examples/, ordocs/subdirectoriesAutomated checks
Enforced by CI (
npm run validate:skills) per the Agent Skills spec:SKILL.mdnamematches directory name;descriptionis present, ≥ 20 words, ≤ 1024 characters, and includes trigger language@W-21685788@