<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet title="XSL_formatting" type="text/xsl" href="https://developer.salesforce.com/blogs/wp-content/themes/dfctheme/includes/feed_styles.xsl" ?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
xmlns:podcast="https://podcastindex.org/namespace/1.0"
xmlns:rawvoice="https://blubrry.com/developer/rawvoice-rss/"
xmlns:media="http://search.yahoo.com/mrss/"
	xmlns:dscblog="https://developer.salesforce.com/blog/dscblog/"
>


<channel>
	<title>Salesforce Developers Blog</title>
	<atom:link href="https://developer.salesforce.com/blogs/feed" rel="self" type="application/rss+xml" />
	<link>https://developer.salesforce.com/blogs</link>
	<description>Elevating developer skills and connecting with the Salesforce Developers community</description>
	<lastBuildDate>Fri, 22 May 2026 23:00:12 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
	<atom:link rel="hub" href="https://pubsubhubbub.appspot.com/" />
	<itunes:author>Salesforce Developers Blog</itunes:author>
	<itunes:explicit>false</itunes:explicit>
	<itunes:image href="https://developer.salesforce.com/blogs/wp-content/plugins/powerpress/itunes_default.jpg" />
	<itunes:owner>
		<itunes:name>Salesforce Developers Blog</itunes:name>
	</itunes:owner>
	<podcast:medium>podcast</podcast:medium>
	<image>
		<title>Salesforce Developers Blog</title>
		<url>https://developer.salesforce.com/blogs/wp-content/plugins/powerpress/rss_default.jpg</url>
		<link>https://developer.salesforce.com/blogs</link>
	</image>
	<podcast:podping usesPodping="true" />
<site xmlns="com-wordpress:feed-additions:1">244780846</site>	<item>
		<title>What Salesforce Headless 360 Means For Developers</title>
		<link>https://developer.salesforce.com/blogs/2026/05/headless-360-what-it-means-for-developers</link>
		<comments>https://developer.salesforce.com/blogs/2026/05/headless-360-what-it-means-for-developers#respond</comments>
		<pubDate>Thu, 21 May 2026 15:02:33 +0000</pubDate>
		<dc:creator><![CDATA[René Winkelmeyer]]></dc:creator>
				<category><![CDATA[Announcements]]></category>
		<category><![CDATA[APIs and Integrations]]></category>
		<category><![CDATA[App Development]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[New Developments]]></category>
		<category><![CDATA[apis]]></category>
		<category><![CDATA[Coding agents]]></category>
		<category><![CDATA[Developers]]></category>
		<category><![CDATA[Governance]]></category>
		<category><![CDATA[Headless 360]]></category>
		<category><![CDATA[MCP tools]]></category>
		<category><![CDATA[Salesforce Platform]]></category>
		<category><![CDATA[System design]]></category>

		<guid isPermaLink="false">https://developer.salesforce.com/blogs/?p=206326</guid>
		<description><![CDATA[<p>Headless 360 exposes every Salesforce capability as an API, MCP tool, or CLI command. Learn why your platform expertise matters more in an agentic world.</p>
<p>The post <a href="https://developer.salesforce.com/blogs/2026/05/headless-360-what-it-means-for-developers">What Salesforce Headless 360 Means For Developers</a> appeared first on <a href="https://developer.salesforce.com/blogs">Salesforce Developers Blog</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p><span style="font-weight: 400">Salesforce Headless 360 makes every major Salesforce capability available as an API, Model Context Protocol (MCP) tool, or CLI command. MCP is a standardized protocol that lets AI models discover and call external tools, APIs, and data sources at runtime, so any compatible client can connect to any compatible server without custom integration code. This post covers what that means when you build on the platform, and why the fundamentals you&#8217;ve been learning matter more than ever.</span></p>
<p><span style="font-weight: 400">As the Salesforce Developer Advocacy team lead, I</span> <a href="https://developer.salesforce.com/blogs/2025/03/future-salesforce-developer-agentic-ai"><span style="font-weight: 400">recently posted on the future of the Salesforce Developer role</span></a><span style="font-weight: 400">. In that post, I argued that AI is reshaping our work around system design, quality engineering, and cross-system thinking. Headless 360 is the platform shift that turns those arguments into daily practice.</span></p>
<h2><span style="font-weight: 400">The platform provides context and capability</span></h2>
<p><span style="font-weight: 400">The LLM provides intelligence. The platform provides everything else: identity, access, capabilities, governance, and the context that makes intelligence useful. When an agent calls an MCP tool, it&#8217;s invoking accumulated state. Without it, the agent has nothing to reason over, no permissions to inherit, no business process to follow.</span></p>
<p><span style="font-weight: 400">This was always true. Every customer record, every workflow, every approval chain, every permission boundary your org has accumulated &#8211; that&#8217;s not overhead. That&#8217;s the business itself, encoded in a system that enforces it.</span></p>
<p><span style="font-weight: 400">That combination of intelligence from the model and everything else from the platform is what separates a prototype from a production system. It&#8217;s also what makes Headless 360 different from “just expose some APIs”.</span></p>
<h2><span style="font-weight: 400">Two kinds of MCP tools</span></h2>
<p><span style="font-weight: 400">When we talk about MCP tools in the Salesforce ecosystem, we mean two things:</span></p>
<ul>
<li style="font-weight: 400"><b>MCP tools for coding agents.</b><span style="font-weight: 400"> These enable developers to connect Claude Code, Cursor, or any MCP-compatible coding agent to their org and read metadata, generate Apex, run tests, or deploy through the pipeline. The consumer is a </span><i><span style="font-weight: 400">developer building software</span></i><span style="font-weight: 400">.</span></li>
<li style="font-weight: 400"><b style="color: #4a4a4a">MCP tools for business agents.</b><span style="font-weight: 400"> These enable </span><span style="font-weight: 400">users to access Salesforce capabilities from any MCP-compatible client: including Slack, ChatGPT, and Claude, among others. These MCP tools also allow agents to access Salesforce capabilities autonomously</span><span style="font-weight: 400">. The consumer is an </span><i style="color: #4a4a4a"><span>agent serving an end user</span></i><span style="font-weight: 400">.</span></li>
</ul>
<p><span style="font-weight: 400">Both kinds of MCP tools share the same open surface and the same trust layer. The difference is who&#8217;s calling and why. Headless 360 covers both, and both have implications for the expertise you&#8217;ve built.</span></p>
<p><span style="font-weight: 400">Headless 360 changes how the platform can be consumed. Coding agents can now reach into your org through MCP tools to build and deploy. Business agents can call the same platform to serve customers in Slack, ChatGPT, Claude, or any MCP-compatible client. The Salesforce browser-based UI is one surface among many.</span><i><span style="font-weight: 400">.</span></i></p>
<h2><span style="font-weight: 400">How software is built, delivered, and used is changing all at once</span></h2>
<p><span style="font-weight: 400">Agentic AI is changing three things simultaneously.</span></p>
<p><b>How software is written.</b><span style="font-weight: 400"> Agents are becoming the development team. The first draft of an Apex class, an LWC, a test suite, or an Agentforce agent arrives in seconds. Your job shifts from writing code to specifying intent, evaluating output, and deciding what fits your existing system design.</span></p>
<p><b>How quickly it is delivered.</b><span style="font-weight: 400"> Implementations compress from months to days. When an agent can execute against a development org, with human review gates before anything reaches production, the bottleneck moves from execution to clarity of intent.</span></p>
<p><b>How it is used.</b><span style="font-weight: 400"> Humans will use Salesforce from anywhere, not necessarily the Salesforce UI. A sales rep gets a customer summary in Slack. A support agent resolves a case in Teams. And increasingly, the consumer isn&#8217;t a human at all; it&#8217;s a business agent reasoning over your data. The destination isn&#8217;t a Lightning Experience tab. It&#8217;s wherever the work is already happening.</span></p>
<p><span style="font-weight: 400">These three changes are happening simultaneously, and they put pressure on the platform itself. </span><b>Headless 360 is the platform shift designed to address all three at once.</b></p>
<table>
<thead>
<tr>
<th><b>Dimension</b></th>
<th><b>Traditional Salesforce</b></th>
<th><b>Headless 360</b></th>
</tr>
</thead>
<tbody>
<tr>
<td><b>Who writes code</b></td>
<td><span style="font-weight: 400">Human developer, start to finish</span></td>
<td><span style="font-weight: 400">Human + coding agent via MCP tools; developer specifies intent and reviews output</span></td>
</tr>
<tr>
<td><b>Implementation timeline</b></td>
<td><span style="font-weight: 400">Weeks to months across multiple roles</span></td>
<td><span style="font-weight: 400">Days; agent executes against development org with human review gates</span></td>
</tr>
<tr>
<td><b>Primary consumer</b></td>
<td><span style="font-weight: 400">Human navigating Lightning UI</span></td>
<td><span style="font-weight: 400">Any authenticated caller &#8211; human, agent, app, or CLI</span></td>
</tr>
</tbody>
</table>
<p><span style="font-weight: 400">In addition to these three core dimensions, Headless 360 also changes how governance is enforced and how you think about channel strategy. When the UI is no longer the primary surface, you can&#8217;t rely on a mix of UI constraints and schema rules for governance; instead, full schema-level enforcement (via validation rules, your sharing model, and Apex) is required. And rather than building per-channel UIs (for Lightning, mobile, and community, for example), with Headless 360 you define a capability once and let it render wherever it&#8217;s called, including Slack, ChatGPT, mobile, or web. </span></p>
<h2><span style="font-weight: 400">What Headless 360 actually is</span></h2>
<p><span style="font-weight: 400">Headless 360 makes every major Salesforce capability openly composable by agents, not just by code paths a human developer wrote in advance. The full surface, including 60+ MCP tools, 30+ coding skills, 4,000+ existing APIs, and 220+ CLI commands, is accessible to any authenticated caller that your trust layer authorizes.</span></p>
<p><span style="font-weight: 400">This isn&#8217;t new territory for Salesforce developers. You&#8217;ve been building headless for years. This includes Experience Cloud sites with React frontends, Node.js apps over REST APIs, and mobile apps via the Mobile SDK. What&#8217;s new is that AI models can now dynamically discover, use, and compose capabilities at runtime, without custom integration code written in advance for each one. </span></p>
<p><span style="font-weight: 400">When we say “openly composable by agents” the </span><i><span style="font-weight: 400">openly</span></i><span style="font-weight: 400"> matters. Openness is the default posture. Governance is what makes it safe.</span></p>
<h2><span style="font-weight: 400">Headless 360 in practice</span></h2>
<p><span style="font-weight: 400">The capabilities Headless 360 unlocks aren&#8217;t abstract. Here&#8217;s what they look like in practice. </span></p>
<h3><span style="font-weight: 400">Build with any coding agent</span></h3>
<p><span style="font-weight: 400">The </span><a href="https://www.salesforce.com/news/stories/salesforce-headless-360-announcement/"><span style="font-weight: 400">60+ MCP tools and 30+ preconfigured coding skills</span></a><span style="font-weight: 400"> give any compatible coding agent live access to your org. </span><a href="https://www.salesforce.com/agentforce/developers/vibe-coding/"><span style="font-weight: 400">Agentforce Vibes 2.0</span></a><span style="font-weight: 400"> brings that natively inside Salesforce, but the MCP surface is the same regardless of which agent you choose.</span></p>
<p><span style="font-weight: 400">Here is a typical session: your coding agent connects to a scratch org via MCP, reads the object model, scaffolds an Apex service class with governor-limit-aware test coverage, and pushes it through your DevOps pipeline. Same deployment gates, same quality checks, same review process as code written by hand. The pipeline doesn&#8217;t care who initiated it. It cares whether the gates pass.</span></p>
<p><span style="font-weight: 400">The platform doesn&#8217;t privilege one agent over another. Your org&#8217;s capabilities are the constant. The tooling around it is your choice. For more on the MCP tools and how they work, see our post </span><a href="https://developer.salesforce.com/blogs/2025/06/introducing-mcp-support-across-salesforce"><span style="font-weight: 400">Introducing MCP Support Across Salesforce</span></a><span style="font-weight: 400">.</span></p>
<h3><span style="font-weight: 400">Render in any UI framework</span></h3>
<p><span style="font-weight: 400">Headless decouples capability from rendering. In practice, this means the platform no longer constrains your UI framework. A clear example of this is </span><a href="https://developer.salesforce.com/blogs/2026/04/build-with-react-run-on-salesforce-introducing-salesforce-multi-framework"><span style="font-weight: 400">multi-framework support</span></a><span style="font-weight: 400">.</span></p>
<p><span style="font-weight: 400">With multi-framework support, React developers can now build on Salesforce using the same patterns they already know, with no requirement to use LWC. A front-end engineer who&#8217;s never touched Salesforce can build a governed, data-connected application using familiar tools, because the platform adapts to their stack.</span></p>
<p><span style="font-weight: 400">That hiring constraint where you needed someone who knew LWC or Aura? It&#8217;s no longer a hard constraint. The platform meets developers where they already are.</span></p>
<h3><span style="font-weight: 400">Deploy on any surface</span></h3>
<p><span style="font-weight: 400">The </span><a href="https://www.salesforce.com/platform/orchestration-platform/"><span style="font-weight: 400">Headless Experience Layer</span></a><span style="font-weight: 400"> is a new runtime that decouples capability definitions from their rendering surface. You define a UI fragment and the Headless Experience Layer (HXL) handles rendering it as a Slack block, a mobile card, a ChatGPT response, or a voice interaction. Business logic, data, and permissions stay separated from the screen, so you define intent once and render natively everywhere, including Slack, mobile, ChatGPT, Claude, Teams, or any MCP-compatible client.</span></p>
<p><span style="font-weight: 400">This is where the two MCP lanes start to converge. The same openness that lets a coding agent build against your org will also let a business agent serve your customers from it. Today, the build-time surface is mature. The runtime surface already supports straightforward use cases, such as a support agent pulling a case summary inside a Slack thread. The broader vision is that the same capability can be delivered across surfaces such as voice interactions or partner mobile apps, and that ultimately capabilities can be made available on any surface.</span></p>
<h3><span style="font-weight: 400">Protect with built-in governance</span></h3>
<p><a href="https://www.salesforce.com/blog/headless-trust-model-agentic-architecture/"><span style="font-weight: 400">Headless doesn&#8217;t mean ungoverned</span></a><span style="font-weight: 400">. Governance is what makes it safe to build with any coding agent, render in any UI framework, and deploy on any surface. </span></p>
<p><span style="font-weight: 400">When a coding agent pushes an Apex class, it goes through the same validation, tests, and deployment gates as code written by a human. When an agent queries customer data through MCP, it hits the same sharing rules and field-level security as a user in Lightning.</span></p>
<p><span style="font-weight: 400">Four things are enforced on every API call, every MCP tool invocation, and every CLI command:</span></p>
<ul>
<li style="font-weight: 400"><b>Identity.</b><span style="font-weight: 400"> The agent acts as a specific user, not an anonymous caller. Permissions are scoped to that identity.</span></li>
<li style="font-weight: 400"><b>Access.</b><span style="font-weight: 400"> Sharing rules, field-level security, and permission sets enforce what the caller can see and do.</span></li>
<li style="font-weight: 400"><b>Invocation scope.</b><span style="font-weight: 400"> The agent can invoke only those tools and actions that have been explicitly exposed.</span></li>
<li style="font-weight: 400"><b>Governance.</b><span style="font-weight: 400"> Validation rules, triggers, approval chains, and governor limits all fire regardless of entry point.</span></li>
</ul>
<p><span style="font-weight: 400">The platform is open about </span><i><span style="font-weight: 400">what</span></i><span style="font-weight: 400"> can be accessed. It is not open about </span><i><span style="font-weight: 400">who</span></i><span style="font-weight: 400"> can access it, or </span><i><span style="font-weight: 400">how</span></i><span style="font-weight: 400">. That&#8217;s what makes it safe for </span><i><span style="font-weight: 400">openness</span></i><span style="font-weight: 400"> to be the default posture.</span></p>
<h2><span style="font-weight: 400">Why most agentic prototypes don&#8217;t reach production</span></h2>
<p><span style="font-weight: 400">If you&#8217;ve tried to ship an agent, you&#8217;ve likely encountered this problem. The demo works. The stakeholder asks a question that breaks it. For example:</span><i></i></p>
<ul>
<li style="font-weight: 400"><i><span style="font-weight: 400">&#8220;Will it respect the sharing rule on this object?&#8221;</span></i></li>
<li style="font-weight: 400"><i><span style="font-weight: 400">&#8220;What happens if the user doesn&#8217;t have permission to update that field?&#8221;</span></i></li>
<li style="font-weight: 400"><i><span style="font-weight: 400">&#8220;How does it know which approval policy applies?&#8221;</span></i></li>
</ul>
<p><span style="font-weight: 400">The LLM alone is not enough. The hard part is everything around it: business context, identity-aware permissions, policy enforcement, and the operational guarantees that make a system safe to run autonomously.</span></p>
<p><b>That gap is exactly what the Salesforce platform fills.</b><span style="font-weight: 400"> The context an agent needs didn&#8217;t show up because someone wrote a clever prompt. It accumulated over years, in your data model, your validation rules, your sharing architecture, your trigger framework. Headless 360 makes that platform accessible to agents through a governed surface. </span><b>You don&#8217;t rebuild context, permissions, or policy for your agents. They inherit it.</b></p>
<p><span style="font-weight: 400">Testing is part of this too. Testing agents is different from testing deterministic code. You&#8217;re evaluating whether an agent&#8217;s reasoning led to an acceptable outcome across a distribution of inputs. Session tracing, custom scoring evals, and the Agentforce Testing Center are how you build confidence that an agent does the right thing in production. The discipline is familiar if you&#8217;ve built test suites for complex Apex, but the techniques are new.</span></p>
<h2><span style="font-weight: 400">What comes next</span></h2>
<p><span style="font-weight: 400">Headless 360 ships with MCP tools for coding and business agents, coding skills, multi-framework support, and the Experience Layer. That&#8217;s its surface. What makes it work is everything underneath: the state, the governance, the accumulated business logic of a platform you already know.</span></p>
<p><span style="font-weight: 400">On the </span><a href="https://developer.salesforce.com/blogs"><span style="font-weight: 400">Salesforce Developer Blog</span></a><span style="font-weight: 400"> and </span><a href="https://www.youtube.com/@salesforcedevs"><span style="font-weight: 400">YouTube</span></a><span style="font-weight: 400">, we&#8217;re going deep on every building block, including skills for coding agents, multi-framework walkthroughs, trust and governance deep dives, testing and observability patterns, and more. Follow along and tell us where to go deeper.</span></p>
<p><span style="font-weight: 400">The platform is open. Build on it.</span></p>
<h2><span style="font-weight: 400">Related Reading</span></h2>
<ul>
<li style="font-weight: 400"><a href="https://developer.salesforce.com/blogs/2026/03/future-salesforce-developer-agentic-ai"><span style="font-weight: 400">The Future of the Salesforce Developer in the Agentic AI Era</span></a></li>
<li style="font-weight: 400"><a href="https://www.salesforce.com/news/stories/salesforce-headless-360-announcement/"><span style="font-weight: 400">Introducing Salesforce Headless 360</span></a></li>
<li style="font-weight: 400"><a href="https://www.salesforce.com/agentforce/developers/vibe-coding/"><span style="font-weight: 400">Agentforce Vibes 2.0</span></a></li>
<li style="font-weight: 400"><a href="https://www.salesforce.com/platform/orchestration-platform/"><span style="font-weight: 400">Headless Experience Layer</span></a></li>
<li style="font-weight: 400"><a href="https://www.salesforce.com/platform/multi-framework/"><span style="font-weight: 400">Salesforce Multi-Framework</span></a></li>
<li style="font-weight: 400"><a href="https://labs.agentforce.com/"><span style="font-weight: 400">Agentforce Labs</span></a></li>
<li style="font-weight: 400"><a href="https://github.com/forcedotcom/afv-library/tree/main/skills/developing-agentforce"><span style="font-weight: 400">Open Source Agentforce Skills</span></a></li>
</ul>
<h2><span style="font-weight: 400">About the Author</span></h2>
<p><b>Rene Winkelmeyer</b><span style="font-weight: 400"> leads the Developer Advocacy team at Salesforce. His team focuses on Agentforce, Data 360, and the Salesforce Platform. In his spare time, you might find him </span><a href="https://github.com/muenzpraeger"><span style="font-weight: 400">still coding on GitHub</span></a><span style="font-weight: 400">. Follow Rene on </span><a href="https://www.linkedin.com/in/muenzpraeger"><span style="font-weight: 400">LinkedIn</span></a><span style="font-weight: 400">.</span></p>
<p>The post <a href="https://developer.salesforce.com/blogs/2026/05/headless-360-what-it-means-for-developers">What Salesforce Headless 360 Means For Developers</a> appeared first on <a href="https://developer.salesforce.com/blogs">Salesforce Developers Blog</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://developer.salesforce.com/blogs/2026/05/headless-360-what-it-means-for-developers/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<post-id xmlns="com-wordpress:feed-additions:1">206326</post-id><media:thumbnail url="https://d259t2jj6zp7qm.cloudfront.net/images/20260521080801/1000x563-B-2.png?w=1000" />
<media:content url="https://d259t2jj6zp7qm.cloudfront.net/images/20260521080801/1000x563-B-2.png?w=1000" medium="image" />
	</item>
		<item>
		<title>Conduct End-to-End Testing for Salesforce Omnistudio-based UIs</title>
		<link>https://developer.salesforce.com/blogs/2026/05/conduct-end-to-end-testing-for-salesforce-omnistudio-based-uis</link>
		<comments>https://developer.salesforce.com/blogs/2026/05/conduct-end-to-end-testing-for-salesforce-omnistudio-based-uis#respond</comments>
		<pubDate>Wed, 20 May 2026 15:00:35 +0000</pubDate>
		<dc:creator><![CDATA[Sarah Welker]]></dc:creator>
				<category><![CDATA[App Development]]></category>
		<category><![CDATA[Automation]]></category>
		<category><![CDATA[Developer Tooling]]></category>
		<category><![CDATA[Lightning Web Components]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[APIs and Integrations]]></category>
		<category><![CDATA[app development]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[developer tooling]]></category>
		<category><![CDATA[devops]]></category>
		<category><![CDATA[Trust Security and Accessibility]]></category>
		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">https://developer.salesforce.com/blogs/?p=206339</guid>
		<description><![CDATA[<p>Stop broken deployments. Learn how to implement stable end-to-end testing for Salesforce Omnistudio UI, leveraging UTAM, Playwright, and specific scenario testing for Omniscripts and Flexcards.</p>
<p>The post <a href="https://developer.salesforce.com/blogs/2026/05/conduct-end-to-end-testing-for-salesforce-omnistudio-based-uis">Conduct End-to-End Testing for Salesforce Omnistudio-based UIs</a> appeared first on <a href="https://developer.salesforce.com/blogs">Salesforce Developers Blog</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p><span style="font-weight: 400">Testing user interfaces (UIs) can feel like trying to hit a moving target, especially when you are working with </span><a href="https://www.salesforce.com/products/omnistudio/overview/"><span style="font-weight: 400">Salesforce Omnistudio components</span></a><span style="font-weight: 400">. You know the drill: you pour hours into crafting an Omniscript for customer onboarding or a Flexcard dashboard for sales teams, and it looks perfect in preview. But then you run user tests and — </span><i><span style="font-weight: 400">bam!</span></i><span style="font-weight: 400"> — stuff breaks in ways you never saw coming.</span></p>
<p><span style="font-weight: 400">Picture your customer rolling out a Flexcard for quick account overviews. It’s looking great on desktop, but on mobile? Actions don&#8217;t fire, data doesn&#8217;t render, and users bounce in frustration. These aren&#8217;t rare moments; they&#8217;re everyday headaches that slow deployments, breaking trust. End-to-end (E2E) testing fixes this mess by mimicking real journeys, so you can catch issues early and deploy with confidence.</span></p>
<h2><b>Why E2E testing matters for Omnistudio</b></h2>
<p><span style="font-weight: 400">So, why do we need to test the entire journey rather than just checking if a button works? Testing the full user journey is critical because </span><a href="https://help.salesforce.com/s/articleView?id=xcloud.os_omniscripts_8355.htm&amp;type=5"><span style="font-weight: 400">Omniscripts</span></a><span style="font-weight: 400">, </span><a href="https://help.salesforce.com/s/articleView?id=xcloud.os_omnistudio_flexcards_24388.htm&amp;type=5"><span style="font-weight: 400">Flexcards</span></a><span style="font-weight: 400">, and </span><a href="https://help.salesforce.com/s/articleView?id=xcloud.os_omnistudio_dataraptors_45587.htm&amp;type=5"><span style="font-weight: 400">Data Mappers</span></a><span style="font-weight: 400"> interact across boundaries where unit tests cannot validate the complete process. E2E testing plays out the full story of what a real user does, from start to finish across your components, like a demo of an actual </span><a href="https://www.salesforce.com/marketing/customer-journey/"><span style="font-weight: 400">customer journey</span></a><span style="font-weight: 400">. </span></p>
<p><span style="font-weight: 400">E2E testing also helps you:</span></p>
<ul>
<li style="font-weight: 400"><b>Simulate full user journeys across Omnistudio components:</b><span style="font-weight: 400"> E2E testing plays out that whole flow, just like a real person clicking through components, spotting weird hiccups along the way.</span></li>
<li style="font-weight: 400"><b>Catch integration issues early for partners building solutions: </b><span style="font-weight: 400">E2E grabs those sneaky spots where Data Mappers don&#8217;t feed data right into an Omniscript, saving you from frantic fixes right before demo day.</span></li>
<li style="font-weight: 400"><b>Reduce post-go-live bugs:</b><span style="font-weight: 400"> E2E irons out production surprises, reducing post-deployment defect tickets for your teams, giving you greater confidence in deployments.</span></li>
<li style="font-weight: 400"><b>Validate real-world flows to record creation:</b><span style="font-weight: 400"> Unit tests poke single buttons (like does this button click? Does that data pull?). E2E runs the full race, like submitting a lead form, watching it zip through conditions, and landing as a shiny new record in Salesforce.</span></li>
<li style="font-weight: 400"><b>Find the real problem:</b><span style="font-weight: 400"> When tests flake, E2E pinpoints the issue past the pretty interface and discovers whether or not the backend logic is actually the part causing the crash.</span></li>
<li style="font-weight: 400"><b>Confirm that the handoff works:</b><span style="font-weight: 400"> Picture Omniscript passing data to a Flexcard. E2E checks that the pass doesn&#8217;t drop, enabling easy jumps between your UI pieces.</span></li>
<li style="font-weight: 400"><b>Manage your own path: </b><span style="font-weight: 400">Users don&#8217;t always go straight. E2E tests the sunny &#8220;submit and succeed&#8221; path plus detours like errors or save-for-later resumes, covering all those branching stories.</span></li>
</ul>
<h2><b>High risk components to test first</b></h2>
<p><span style="font-weight: 400">When figuring out where to focus your testing energy, it helps to know which parts of the system are most likely to break. Based on what teams see in the real world, here are the high-risk areas you need to watch.</span></p>
<p><b>Omniscripts</b><span style="font-weight: 400"> account for approximately 50% of reported Omnistudio UI bugs, making them the highest-priority target for E2E testing. Because this is the layer the user interacts with directly and is also most visible, it typically receives the highest number of reported bugs. They juggle steps, conditions, inputs, and data swaps with Data Mappers all in one go. Mess up here, and your whole customer journey, like a service request form, grinds to a halt.</span></p>
<p><span style="font-weight: 400">Next is </span><b>Flexcards</b><span style="font-weight: 400"> because these cards are used to display critical data and handle user actions, and any glitch here is immediately obvious to the user. </span></p>
<p><span style="font-weight: 400">Finally, we have </span><b>Data Mappers</b><span style="font-weight: 400">. If mappings fail (say, wrong field names or null values), Omniscripts starve for information, also breaking Flexcards downstream.</span></p>
<p><b>Note:</b><span style="font-weight: 400"> All data presented above is derived from internal testing.</span></p>
<h2><b>Tools for Omnistudio test automation: UTAM, Playwright, and Selenium</b></h2>
<p><a href="https://www.salesforce.com/artificial-intelligence/what-is-automation/"><span style="font-weight: 400">Automation</span></a><span style="font-weight: 400"> sounds cool, but here&#8217;s the headache: </span><a href="https://www.salesforce.com/industries/omnistudio/omnistudio-on-core-guide/"><span style="font-weight: 400">Omnistudio</span></a><span style="font-weight: 400"> pieces shift a lot. You might spend days building a perfect test script, and it runs beautifully, until the next release drops. Suddenly, everything breaks. Why? The main culprit here is dynamic element IDs. Because Omniscripts and Flexcards are built on </span><a href="https://developer.salesforce.com/developer-centers/lightning-web-components"><span style="font-weight: 400">Lightning Web Components (LWC)</span></a><span style="font-weight: 400">, they sit inside a </span><a href="https://developer.salesforce.com/docs/platform/lwc/guide/create-dom.html"><span style="font-weight: 400">Shadow DOM</span></a><span style="font-weight: 400">. So your usual CSS or XPath selectors become fragile and start failing whenever Salesforce moves with seasonal updates. It breaks everything at the backend. One day your test clicks Submit just fine, and the next, it hunts for a button that moves and your whole pipeline stalls.</span></p>
<p><span style="font-weight: 400">To solve this problem, Salesforce created the </span><a href="https://utam.dev/"><span style="font-weight: 400">UI test automation model (UTAM)</span></a><span style="font-weight: 400">, a proprietary tool designed specifically for LWC in Omnistudio. Omnistudio components are wrapped in Shadow Roots (that&#8217;s the Shadow DOM), which blocks standard Selenium selectors like CSS or XPath from reaching elements reliably, especially after Salesforce updates.</span></p>
<pre class="wp-block-code language-xml">&lt;!-- Source: https://mvnrepository.com/artifact/com.salesforce.utam/salesforce-pageobjects --&gt;
&lt;dependency&gt;
    &lt;groupId&gt;com.salesforce.utam&lt;/groupId&gt;
    &lt;artifactId&gt;salesforce-pageobjects&lt;/artifactId&gt;
    &lt;version&gt;12.0.0&lt;/version&gt;
    &lt;scope&gt;compile&lt;/scope&gt;
&lt;/dependency&gt;</pre>
<p><span style="font-weight: 400">Instead of relying on brittle selectors in scripts, UTAM uses JSON-based page objects. When a button’s location or structure changes in an Omnistudio update, you just update the </span><a href="https://help.salesforce.com/s/articleView?id=data.c360_a_activation_toolkit_isv.htm&amp;type=5"><span style="font-weight: 400">JSON metadata</span></a><span style="font-weight: 400"> once, and all your tests are instantly back on track. It creates a stable layer and lets scripts identify UI components consistently, no matter what changes underneath.</span>
			  <span class="postimagessection_specify alignnone size-medium wp-image-206351" >
			    <img fetchpriority="high" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260515104345/Screenshot-of-example-UTAM-code-e1778867167835.png?w=1000" class="postimages" width="1000" height="583" alt="Screenshot of example UTAM code" />
			  </span>
			</p>
<h3><span style="font-weight: 400">Choosing between UTAM, Playwright, and Selenium</span></h3>
<p><span style="font-weight: 400">Instead of relying on fragile identifiers, a smart move would be to grab the right tools that don&#8217;t flake. Use a combination of industry-standard tools and Salesforce-specific frameworks. Here&#8217;s when to use what:</span></p>
<ul>
<li style="font-weight: 400"><b>UTAM:</b><span style="font-weight: 400"> Best for long-term maintenance and Salesforce-native components, giving you those stable JSON selectors that survive Omnistudio updates.</span></li>
<li style="font-weight: 400"><b>Playwright:</b> <a href="https://playwright.dev/"><span style="font-weight: 400">Playwright</span></a><span style="font-weight: 400"> is best for speed and headless </span><a href="https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/ci-cd.html"><span style="font-weight: 400">CI/CD</span></a><span style="font-weight: 400"> pipelines. Fire it up without a visible browser to debug fast across browsers. </span></li>
<li style="font-weight: 400"><b>Cucumber with Selenium:</b> <a href="https://cucumber.io/"><span style="font-weight: 400">Cucumber</span></a><span style="font-weight: 400"> with</span><a href="https://www.selenium.dev/"> <span style="font-weight: 400">Selenium</span></a><span style="font-weight: 400"> is best for business stakeholder sign-off (BDD). You write tests in plain English and your team reads and approves it.</span></li>
</ul>
<p><span style="font-weight: 400">Launch with tweaks like test parameters (</span><a href="https://www.salesforce.com/in/platform/sandboxes-environments/"><span style="font-weight: 400">sandbox</span></a><span style="font-weight: 400"> mode? Slow it down?). Then poke issues using element properties. Is it visible? Enabled? That&#8217;s how you spot and squash the real culprits without endless rewrites.</span></p>
<table>
<tbody>
<tr>
<td><b>Feature</b></td>
<td><b>UTAM (UI Test Automation Model)</b></td>
<td><b>Playwright</b></td>
<td><b>Cucumber + Selenium</b></td>
</tr>
<tr>
<td><b>Primary Use Case</b></td>
<td><span style="font-weight: 400">Salesforce-specific UI testing and complex Shadow DOMs</span></td>
<td><span style="font-weight: 400">Modern web apps (React, Vue, etc.) and high-speed CI/CD</span></td>
<td><span style="font-weight: 400">Legacy apps and BDD (Business Driven Development)</span></td>
</tr>
<tr>
<td><b>Philosophy</b></td>
<td><span style="font-weight: 400">Model-based: Decouples UI via JSON-based page objects</span></td>
<td><span style="font-weight: 400">Modern/native: Direct browser control via WebSockets</span></td>
<td><span style="font-weight: 400">Driver-based: Uses WebDriver to remote-control the browser</span></td>
</tr>
<tr>
<td><b>Wait Handling</b></td>
<td><span style="font-weight: 400">Explicit waits designed into JSON page objects</span></td>
<td><span style="font-weight: 400">Auto-waiting: Automatically waits for elements to be actionable</span></td>
<td><span style="font-weight: 400">Manual: Requires explicit/implicit wait statements (often flaky)</span></td>
</tr>
<tr>
<td><b>Learning Curve</b></td>
<td><span style="font-weight: 400">High: Requires learning UTAM JSON grammar and compiler</span></td>
<td><span style="font-weight: 400">Low: Very beginner-friendly with excellent documentation</span></td>
<td><span style="font-weight: 400">Moderate: Large community, but setup is complex</span></td>
</tr>
<tr>
<td><b>Language Support</b></td>
<td><span style="font-weight: 400">Java, JavaScript, TypeScript</span></td>
<td><span style="font-weight: 400">JS, TS, Python, Java, .NET</span></td>
<td><span style="font-weight: 400">Almost any (Java, Python, C#, Ruby, PHP, Perl)</span></td>
</tr>
<tr>
<td><b>Parallelization</b></td>
<td><span style="font-weight: 400">Managed by the runner (e.g., WebdriverIO/JUnit)</span></td>
<td><span style="font-weight: 400">Native: Extremely fast via isolated Browser Contexts</span></td>
<td><span style="font-weight: 400">Requires Selenium Grid (resource-heavy)</span></td>
</tr>
<tr>
<td><b>Standout Feature</b></td>
<td><span style="font-weight: 400">Shadow DOM support: Pierces Salesforce&#8217;s complex DOM layers</span></td>
<td><span style="font-weight: 400">Trace Viewer: Time-travel debugging with video and logs</span></td>
<td><span style="font-weight: 400">Gherkin Syntax: Tests written in plain English (Given/When/Then)</span></td>
</tr>
</tbody>
</table>
<h2><b>Testing scenarios by Omnistudio component</b></h2>
<p><span style="font-weight: 400">Now that we&#8217;ve covered the hurdles, let&#8217;s get practical: what exact scenarios should you click, check, and validate in your Omnistudio flows? Since Omnistudio is made up of different building blocks, we need to look at them individually. Here are the recommended testing scenarios to keep your application running smoothly.</span></p>
<p><span style="font-weight: 400">These are the must-hit spots to make sure everything hangs together for real users.</span></p>
<h3><span style="font-weight: 400">Omniscript testing</span></h3>
<p><span style="font-weight: 400">These are your flow bosses, so test the moves that users make every day.</span></p>
<ul>
<li style="font-weight: 400"><b>Check step transitions &amp; logic: </b><span style="font-weight: 400">Don&#8217;t just check if the Next button works. You need to validate the conditional visibility. This is the if/else logic, if a user selects Option A, does the form show them the correct follow-up question? If they select Option B, does it take them down the alternative path?<br />

			  <span class="postimagessection_specify alignnone size-medium wp-image-206349" >
			    <img decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260515104341/Omniscript-configuration-panel-showing-Conditional-View-settings-e1778867141557.png?w=1000" class="postimages" width="1000" height="189" alt="Omniscript configuration panel showing Conditional View settings." />
			  </span>
			<br />
</span></li>
<li><b>Validation rules:</b><span style="font-weight: 400"> Try to break it. Enter the wrong date format or leave a required field blank. Does the system stop you with a helpful error message (validation failure), or does it let you proceed and crash later?<br />

			  <span class="postimagessection_specify alignnone size-medium wp-image-206341" >
			    <img decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260515104321/Omniscript-property-panel-highlighting-a-required-text-field-e1778867033289.png?w=1000" class="postimages" width="1000" height="163" alt="Omniscript property panel highlighting a required text field." />
			  </span>
			<br />
</span></li>
<li style="font-weight: 400"><b>Save and resume: </b><span style="font-weight: 400">This is a big one. For long applications, users might not finish in one sitting. You must test the &#8220;Save for Later&#8221; functionality to ensure that their data is actually saved and can be resumed exactly where they left off without data loss.<br />

			  <span class="postimagessection_specify alignnone size-medium wp-image-206350" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260515104343/Omniscript-form-preview-featuring-a-Save-for-later-button-e1778867153783.png?w=1000" class="postimages" width="1000" height="804" alt="Omniscript form preview featuring a Save for later button." />
			  </span>
			<br />
</span></li>
<li style="font-weight: 400"><b>The ID trap: </b><span style="font-weight: 400">When automating these tests, avoid using dynamic IDs generated by the browser as these change frequently. Instead, use </span><span style="font-weight: 400">data-testid</span><span style="font-weight: 400"> or stable CSS selectors. This keeps your test from breaking every time Salesforce updates the platform.<br />

			  <span class="postimagessection_specify alignnone size-medium wp-image-206345" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260515104329/Developer-tools-inspecting-an-Omniscripts-nested-LWC-DOM-structure-e1778867088676.png?w=1000" class="postimages" width="1000" height="718" alt="Developer tools inspecting an Omniscript's nested LWC DOM structure." />
			  </span>
			<br />
</span></li>
</ul>
<h3><span style="font-weight: 400">Flexcard testing</span></h3>
<p><span style="font-weight: 400">If Omniscript is the form, the Flexcard is the dashboard that needs to look sharp and act right. It displays data and offers quick actions.</span></p>
<ul>
<li style="font-weight: 400"><b>Validate data rendering: </b><span style="font-weight: 400">First, perform simple visual checks. Is the data showing up? Whether it is static info or contextual data pulled from the system, it needs to render correctly on the screen.<br />

			  <span class="postimagessection_specify alignnone size-medium wp-image-206346" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260515104331/Flexcard-datatable-rendering-various-complaint-records-e1778867100422.png?w=1000" class="postimages" width="1000" height="80" alt="Flexcard datatable rendering various complaint records." />
			  </span>
			<br />
</span></li>
<li style="font-weight: 400"><b>Action buttons:</b><span style="font-weight: 400"> Flexcards aren&#8217;t just for looking, they have buttons. Test these actions specifically. Does clicking the button successfully launch the correct Omniscript or navigate the user to the right page?<br />

			  <span class="postimagessection_specify alignnone size-medium wp-image-206347" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260515104337/Flexcard-designer-displaying-an-action-button-configured-for-Omnianalytics-e1778867114967.png?w=1000" class="postimages" width="1000" height="347" alt="Flexcard designer displaying an action button configured for Omnianalytics." />
			  </span>
			<br />
</span></li>
<li style="font-weight: 400"><b>Conditional states:</b><span style="font-weight: 400"> Just like Omniscripts, Flexcards can change based on data. Test these conditional states, such as hover effects or expanded details, to ensure that the card looks different when it is supposed to.<br />

			  <span class="postimagessection_specify alignnone size-medium wp-image-206348" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260515104339/Flexcard-property-panel-detailing-custom-condition-rules-e1778867128147.png?w=1000" class="postimages" width="1000" height="569" alt="Flexcard property panel detailing custom condition rules." />
			  </span>
			<br />
</span></li>
<li style="font-weight: 400"><b>Selectors:</b><span style="font-weight: 400"> Stick to </span><a href="https://developer.salesforce.com/developer-centers/integration-apis"><span style="font-weight: 400">application programming interface (API)</span></a><span style="font-weight: 400"> name–based selectors for your automation to keep things stable. They stay reliable when Salesforce tweaks the UI.</span></li>
</ul>
<h3><span style="font-weight: 400">Data Mapper testing</span></h3>
<p><span style="font-weight: 400">Now we are moving backstage. Data Mappers are responsible for moving data in and out of Salesforce. Even if the UI looks fine, a broken Data Mapper means the process fails.</span></p>
<ul>
<li style="font-weight: 400"><b>Test separately: </b><span style="font-weight: 400">You don&#8217;t always need the UI to test these. Isolate them to see if they work on their own since they&#8217;re data pipes.<br />

			  <span class="postimagessection_specify alignnone size-medium wp-image-206342" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260515104322/Data-Mapper-debug-interface-showing-a-successful-JSON-execution-e1778867047945.png?w=1000" class="postimages" width="1000" height="196" alt="Data Mapper debug interface showing a successful JSON execution." />
			  </span>
			<br />
</span></li>
<li style="font-weight: 400"><b>Input and mappings:</b><span style="font-weight: 400"> Check the input payload correctness. If you send data in, does it map to the correct fields in the database?<br />

			  <span class="postimagessection_specify alignnone size-medium wp-image-206344" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260515104327/Data-Mapper-screen-displaying-JSON-input-to-output-mappings-e1778867074871.png?w=1000" class="postimages" width="1000" height="390" alt="Data Mapper screen displaying JSON input to output mappings." />
			  </span>
			<br />
</span></li>
<li style="font-weight: 400"><b>Edge cases:</b><span style="font-weight: 400"> What happens if a field is missing or comes through as null? You need to test these edge cases to make sure that the Data Mapper doesn&#8217;t just crash when the data isn&#8217;t perfect.<br />

			  <span class="postimagessection_specify alignnone size-medium wp-image-206343" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260515104325/Data-Mapper-options-dialog-highlighting-null-value-handling-e1778867060927.png?w=1000" class="postimages" width="1000" height="553" alt="Data Mapper options dialog highlighting null value handling." />
			  </span>
			<br />
</span></li>
</ul>
<h3><span style="font-weight: 400">Integration Procedures (IPs) testing </span></h3>
<p><span style="font-weight: 400">Omnistudio’s</span> <a href="https://developer.salesforce.com/docs/atlas.en-us.industries_reference.meta/industries_reference/omnistudio_integration_procedure_apis.htm"><span style="font-weight: 400">Integration Procedures </span></a><span style="font-weight: 400">is like an engine room that handles multiple steps and actions at once.</span></p>
<ul>
<li style="font-weight: 400"><b>Orchestration sequence:</b><span style="font-weight: 400"> Verify that the sequence fires in the right order without skips. Does the Integration Procedure call the Data Mapper, then the external API, and then send the email?<br />

			  <span class="postimagessection_specify alignnone size-medium wp-image-206340" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260515104317/Integration-Procedure-canvas-displaying-a-successful-sequential-flow-of-actions-e1778867019298.png?w=1000" class="postimages" width="1000" height="521" alt="Integration Procedure canvas displaying a successful sequential flow of actions." />
			  </span>
			<br />
</span></li>
<li style="font-weight: 400"><b>Error branching and timeouts:</b><span style="font-weight: 400"> It’s critical to test system failures.&#8221; What happens if an external service takes too long to respond (timeout handling)? Does the IP handle the error gracefully, or does the whole screen freeze?</span></li>
<li style="font-weight: 400"><b>Mock services:</b><span style="font-weight: 400"> In your lower testing environments (like sandbox), use mock services to simulate external responses. This lets you test the logic without relying on (or waiting for) real-world third-party systems.</span></li>
</ul>
<h2><b>Pretesting checklist for Omnistudio </b></h2>
<p><span style="font-weight: 400">Before you even write your first test script or click Run, there are some best practices that you should keep in mind. Testing isn&#8217;t just about finding bugs; it’s about making sure that the design actually works for the human using it.</span></p>
<p><span style="font-weight: 400">Here is a checklist of what to consider before you start testing.</span></p>
<h3><span style="font-weight: 400">Verify backend object updates</span></h3>
<p><span style="font-weight: 400">Don&#8217;t get too distracted by the flashy buttons just yet. Start with the win you want. Your primary goal is to verify that the business actually got what it needed. We call this testing the &#8220;happy path,&#8221; the core journey where everything goes right.</span></p>
<p><span style="font-weight: 400">Ask yourself: When the user hits Submit, did the data actually land where it was supposed to? You need to confirm that the backend S-objects or business objects were updated correctly. If the form looks great but the database is empty, the test has failed.</span></p>
<h3><span style="font-weight: 400">Test dynamic UI state changes</span></h3>
<p><span style="font-weight: 400">Omnistudio interfaces are dynamic. They change based on who is looking at them. For example, a Flexcard might display different contextual data depending on the customer.</span></p>
<p><span style="font-weight: 400">Before testing, verify that the UI visibility logic is sound. Does the screen state change correctly when new info is added? Are buttons going gray when they&#8217;re not ready? You need to ensure that the interface is displaying the right information at the right time.</span></p>
<h3><span style="font-weight: 400">Validate responsive UX</span></h3>
<p><span style="font-weight: 400">Step back and think about the user: does the flow feel natural on a phone or desktop? Test responsive tweaks and little touches like smooth transitions — no janky jumps that make users ditch the app mid-task. The Omniscript is the &#8220;face&#8221; of your application, and because it is the part that users touch, it usually receives the highest number of bug reports.</span></p>
<p><span style="font-weight: 400">However, remember that a bad UX isn&#8217;t always a code error, sometimes it&#8217;s just a confusing design. When planning your tests, think about the flow. Is it intuitive? Since the root cause of a UI bug is often actually a backend configuration issue, ensuring a smooth UX means making sure that the backend supports the frontend easily.</span></p>
<h3><span style="font-weight: 400">Test error messaging paths</span></h3>
<p><span style="font-weight: 400">What happens when things go wrong? Your testing plan needs to cover more than just success stories. You must account for &#8220;unhappy paths,&#8221; such as validation failures where a user enters the wrong data.</span></p>
<p><span style="font-weight: 400">You also need to verify how the system handles big failures, like an Integration Procedure timeout or an </span><a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_intro_what_is_apex.htm"><span style="font-weight: 400">Apex</span></a><span style="font-weight: 400"> exception. Does the user get a helpful error message, or does the screen just freeze? Check that success pop-ups say things like &#8220;Claim submitted, thanks!&#8221; and errors spell out next steps, like &#8220;Missing phone number, add it here,&#8221; instead of vague tech jargon.</span></p>
<h3><span style="font-weight: 400">Accessibility verification</span></h3>
<p><span style="font-weight: 400">Don&#8217;t leave anyone behind — this is non-negotiable. When designing and testing Omniscripts, you must consider accessibility because the UI needs to work for everyone.</span></p>
<p><span style="font-weight: 400">Your tests should ensure that the application caters to all customers, including those who may be visually impaired. Test for screen readers announcing fields correctly, keyboard-only navigation through your Flexcards, and color contrasts that pop for all eyes.</span></p>
<h3><span style="font-weight: 400">Conditional navigation outcomes</span></h3>
<p><span style="font-weight: 400">Finally, where does the user go next? Omnistudio relies heavily on conditional logic, basically if/else statements that send users down different paths based on their choices.</span></p>
<p><span style="font-weight: 400">You need to verify these alternative paths. If a user clicks Save for Later, does the system actually let them resume later without losing data? If they answer Yes to a specific question, does the navigation direct them to the correct follow-up screen? Make sure that every road leads to the right destination.</span></p>
<h2><span style="font-weight: 400">Next steps</span></h2>
<p><span style="font-weight: 400">There you have it. Tackling Omnistudio testing in the simplest way possible without it being a nightmare of flaky scripts and hidden bugs. Start with your highest-traffic Omniscript. Write one UTAM page object for its first step, validate a single field input and step transition, and run it against your sandbox. Once that passes reliably across two Salesforce releases, expand coverage to the scenarios listed above. Build rock-solid flows with clear messaging and confident deployments that your customers love.</span></p>
<h2><b>Resources</b></h2>
<p><span style="font-weight: 400">Video: </span><a href="https://www.youtube.com/watch?v=FV7u7s7i5CY"><span style="font-weight: 400">FlexCards and OmniScripts | Salesforce Industries</span></a><span style="font-weight: 400"> </span></p>
<p><span style="font-weight: 400">Trailhead: </span><a href="https://trailhead.salesforce.com/content/learn/modules/omnistudio-development-essentials"><span style="font-weight: 400">Omnistudio Development Essentials</span></a><span style="font-weight: 400"> </span></p>
<p><span style="font-weight: 400">Trailhead: </span><a href="https://trailhead.salesforce.com/content/learn/modules/omnistudio-omniscript-fundamentals"><span style="font-weight: 400">Omnistudio Omniscript Fundamentals</span></a></p>
<p><span style="font-weight: 400">Video: </span><a href="https://youtu.be/x7kwVCFpKyM?si=k7V_kyNXkUpMv1q4"><span style="font-weight: 400">Build Low-Code Digital Experiences with All-New OmniStudio  | TDX Bengaluru</span></a><span style="font-weight: 400"> </span></p>
<h2><b>About the authors</b></h2>
<p><b>Anjali Gupta</b><span style="font-weight: 400"> is a Senior Product Manager at Salesforce who is specialised in horizontal cloud and platform. She is focused on Omnistudio roadmap and strategies ensuring customer growth and success. Follow her on </span><a href="https://in.linkedin.com/in/anjigupta"><span style="font-weight: 400">LinkedIn</span></a><span style="font-weight: 400">.</span></p>
<p><b>Payal Verma</b><span style="font-weight: 400"> is a Content Marketing Analyst at Salesforce with over four years of professional experience in product, brand, and content marketing. She has worked across both B2B and B2C markets, developing and executing content strategies for a wide range of formats, including blogs, social media, scripts, eBooks, and guides. Follow her on </span><a href="https://www.linkedin.com/in/payal-verma-writer-marketer/"><span style="font-weight: 400">LinkedIn</span></a><span style="font-weight: 400">.</span></p>
<p>The post <a href="https://developer.salesforce.com/blogs/2026/05/conduct-end-to-end-testing-for-salesforce-omnistudio-based-uis">Conduct End-to-End Testing for Salesforce Omnistudio-based UIs</a> appeared first on <a href="https://developer.salesforce.com/blogs">Salesforce Developers Blog</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://developer.salesforce.com/blogs/2026/05/conduct-end-to-end-testing-for-salesforce-omnistudio-based-uis/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<post-id xmlns="com-wordpress:feed-additions:1">206339</post-id><media:thumbnail url="https://d259t2jj6zp7qm.cloudfront.net/images/20260515142805/Generic-B-e1778880497342.png?w=1000" />
<media:content url="https://d259t2jj6zp7qm.cloudfront.net/images/20260515142805/Generic-B-e1778880497342.png?w=1000" medium="image" />
	</item>
		<item>
		<title>Use Custom Lightning Types in Agent Script for Rich Agent UI</title>
		<link>https://developer.salesforce.com/blogs/2026/05/use-custom-lightning-types-in-agent-script-for-rich-agent-ui</link>
		<comments>https://developer.salesforce.com/blogs/2026/05/use-custom-lightning-types-in-agent-script-for-rich-agent-ui#respond</comments>
		<pubDate>Tue, 19 May 2026 15:00:49 +0000</pubDate>
		<dc:creator><![CDATA[Mohith Shrivastava]]></dc:creator>
				<category><![CDATA[Agentforce]]></category>
		<category><![CDATA[Apex]]></category>
		<category><![CDATA[App Development]]></category>
		<category><![CDATA[Developer Tooling]]></category>
		<category><![CDATA[Lightning Web Components]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Agent Script]]></category>
		<category><![CDATA[Agent Script Decoded]]></category>
		<category><![CDATA[Agentic UI]]></category>
		<category><![CDATA[Custom Lightning Types]]></category>
		<category><![CDATA[Headless Experience Layer]]></category>
		<category><![CDATA[lwc]]></category>
		<category><![CDATA[salesforce developers]]></category>

		<guid isPermaLink="false">https://developer.salesforce.com/blogs/?p=206313</guid>
		<description><![CDATA[<p>Use Custom Lightning Types to embed LWCs directly into Agentforce. Build validated forms and rich cards to handle complex enterprise workflows with ease, ensuring a structured and high-fidelity user experience.</p>
<p>The post <a href="https://developer.salesforce.com/blogs/2026/05/use-custom-lightning-types-in-agent-script-for-rich-agent-ui">Use Custom Lightning Types in Agent Script for Rich Agent UI</a> appeared first on <a href="https://developer.salesforce.com/blogs">Salesforce Developers Blog</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p><span style="font-weight: 400">Agentforce is conversational by default. Users type a message and the agent responds with text. This works great for most use cases, but many enterprise workflows demand more. Businesses need forms with dropdowns, input validation, and structured output, and they need it right inside the agent conversation.</span></p>
<p><a href="https://developer.salesforce.com/docs/platform/lightning-types/guide/lightning-types-core.html"><span style="font-weight: 400">Custom Lightning types</span></a><span style="font-weight: 400"> (CLTs) meet this need. They let you render </span><a href="https://developer.salesforce.com/docs/platform/lwc/guide"><span style="font-weight: 400">Lightning Web Components </span></a><span style="font-weight: 400">(LWC) directly within Agentforce experiences in Lightning Experience, </span><a href="https://help.salesforce.com/s/articleView?id=service.enhanced_chat_v2_intro.htm&amp;type=5"><span style="font-weight: 400">Enhanced Chat v2</span></a><span style="font-weight: 400">, and Experience Builder. You can collect structured input through a custom form and display results as rich, styled cards or in your own custom-designed user interface. CLTs are also the foundation of </span><b>Headless</b><a href="https://www.salesforce.com/platform/orchestration-platform/"><b> Experience Layer</b></a><span style="font-weight: 400">, announced at TDX 2026, which extends rich agentic UI beyond Salesforce — to Slack, ChatGPT, and more. </span><b>Define Once, Deploy Anywhere, Secure Everywhere</b><span style="font-weight: 400"> — that&#8217;s the headless experience layer vision. Building with CLTs today means you&#8217;re already working with the primitives that power the next generation of multi-surface agentic experiences.</span></p>
<p><span style="font-weight: 400">This post walks through how to work with CLTs in Agent Script to render a rich experience within Agentforce. All code examples come from the </span><a href="https://github.com/trailheadapps/agent-script-recipes/tree/main/force-app/main/02_actionConfiguration/customLightningTypes"><span style="font-weight: 400">Agent Script Custom Lightning Type</span></a><span style="font-weight: 400"> example recipe.</span></p>
<h2><b>What are custom Lightning types in Agentforce?</b></h2>
<p><span style="font-weight: 400">Custom Lightning types create a bridge between your Agent Script, your actions backed by Apex or flows, and your LWC components. They override the default text-based UI with custom LWC components for both input and output.</span></p>
<p><span style="font-weight: 400">Below is an example of custom Lightning types in action within the Agentforce experience.</span></p>
<p>
			  <span class="postimagessection_specify alignnone size-medium wp-image-206315" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260513112452/image4.png?w=586" class="postimages" width="586" height="1000" alt="Lightning types in the Agentforce experience" />
			  </span>
			</p>
<p><span style="font-weight: 400">The connection flows through three layers:</span></p>
<ul>
<li style="font-weight: 400"><a href="https://developer.salesforce.com/blogs/2026/02/agent-script-decoded-intro-to-agent-script-language-fundamentals"><b>Agent Script</b></a><span style="font-weight: 400"> declares which action parameters need custom UI</span></li>
<li style="font-weight: 400"><b>A Lightning Type Bundle</b><span style="font-weight: 400"> maps each parameter type to an Apex data shape and an LWC component</span></li>
<li style="font-weight: 400"><b>An LWC</b><span style="font-weight: 400"> renders the user interface inside the conversation</span></li>
</ul>
<p><span style="font-weight: 400">This three-layer wiring enables you to keep a clean separation of concerns. Your Agent Script handles orchestration, Apex handles the data shape definition and the business logic, and LWC handles the final user experience.</span><span style="font-weight: 400"><br />
</span><span style="font-weight: 400"></span></p>
<p><span style="font-weight: 400">The following diagram shows how a custom Lightning type is mapped with Agent Script and LWCs.</span></p>
<p>
			  <span class="postimagessection_specify alignnone size-medium wp-image-206316" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260513112527/image2_45401c-e1778696741486.png?w=1000" class="postimages" width="1000" height="546" alt="Custom Lightning type mapping with Agent Script action and LWCs" />
			  </span>
			</p>
<p><span style="font-weight: 400">The following sections describe how to build and wire this connection step-by-step.</span></p>
<h2><b>Step 1: Prepare and deploy your Apex and LWC </b></h2>
<h3><b>Defining the Apex data shape</b></h3>
<p>Each CLT needs an Apex class that defines the data structure. Use inner classes within your service class, with each field annotated with <code>@InvocableVariable</code>. The Lightning Type Bundle references these inner classes as the schema source.</p>
<pre language="apex">public class CaseInput {
    @InvocableVariable(label='Subject' required=true)
    public String subject;

    @InvocableVariable(label='Priority')
    public String priority;

    @InvocableVariable(label='Description')
    public String description;
}
</pre>
<p>One important detail: the wrapper class field names must exactly match the action parameter names from your Agent Script. If your action input is called <code>case_data</code>, the request wrapper field must also be named <code>case_data</code>. A mismatch here silently breaks the entire CLT connection.</p>
<p><b>View the code</b><b>:</b> See the full<a href="https://www.google.com/search?q=https://github.com/trailheadapps/agent-script-recipes"> </a><a href="https://github.com/trailheadapps/agent-script-recipes/blob/main/force-app/main/02_actionConfiguration/customLightningTypes/classes/CaseSubmissionService.cls"><u>CaseSubmissionService.cls</u></a> for the complete Apex implementation including the request/response wrappers.</p>
<h3><b>Building the editor and renderer LWC</b></h3>
<p>The editor LWC collects user input inside the chat. Two things make it work with Agentforce: the meta XML must target <code>lightning__AgentforceInput</code> with a <code>targetType</code> matching the CLT name, and the component must dispatch a <code>valuechange</code> event whenever the user modifies the form.</p>
<pre class="wp-block-code language-xml"> &lt;target&gt;lightning__AgentforceInput&lt;/target&gt;
 &lt;targetType name="c__caseInput" /&gt;
</pre>
<p>The <code>valuechange</code> event payload field names must match the Apex CaseInput class fields. The platform listens for this event to capture and forward the form data to your Apex action.</p>
<p>Here is the simple example snippet showing the <code>valuechange</code> event in practice:</p>
<pre language="js">import { LightningElement } from 'lwc';

export default class CustomCaseForm extends LightningElement {
    // Local state variables for the form
    subject = '';
    priority = 'Medium';
    description = '';

    // Handler triggered when the user types in the Subject input
    handleSubjectChange(event) {
        // 1. Update the specific field that changed
        this.subject = event.target.value;

        // 2. Dispatch the FULL state of the form
        this.dispatchFormState();
    }

    // You would have similar handlers for Priority and Description...

    // Centralized method to dispatch the complete current state
    dispatchFormState() {
        this.dispatchEvent(
            new CustomEvent('valuechange', {
                detail: {
                    value: {
                        // ALWAYS include all fields to match the Apex CaseInput class
                        subject: this.subject,
                        priority: this.priority,
                        description: this.description
                    }
                }
            })
        );
    }
}
</pre>
<p>The renderer LWC displays the result card after the action completes. It targets <code>lightning__AgentforceOutput</code> with a <code>sourceType</code> (not <code>targetType</code>). The component receives the full result object via <code>@api value</code> and uses getters to render the fields with Salesforce Lightning Design System styling.</p>
<pre class="wp-block-code language-xml">&lt;target&gt;lightning__AgentforceOutput&lt;/target&gt;
&lt;sourceType name="c__caseResult" /&gt;</pre>
<p><b>View the code</b><b>:</b><span style="font-weight: 400"> See the full </span><a href="https://github.com/trailheadapps/agent-script-recipes/tree/main/force-app/main/02_actionConfiguration/customLightningTypes/lwc/caseInputEditor"><span style="font-weight: 400">caseInputEditor</span></a><span style="font-weight: 400"> and </span><a href="https://github.com/trailheadapps/agent-script-recipes/tree/main/force-app/main/02_actionConfiguration/customLightningTypes/lwc/caseResultRenderer"><span style="font-weight: 400">caseResultRenderer</span></a> <span style="font-weight: 400">components in the repo.</span></p>
<h3><b>Wiring Lightning type bundles</b></h3>
<p>The Lightning Type Bundle is a folder containing JSON configuration files. The <code>schema.json</code> file points to your Apex inner class using <code>$</code> syntax. For example, <code>c__CaseSubmissionService$CaseInput</code> references the <code>CaseInput</code> inner class.</p>
<pre language="json">{
    "title": "Case Input",
    "lightning:type": "@apexClassType/c__CaseSubmissionService$CaseInput"
}
</pre>
<p>A second file tells the platform which LWC component to render. Input types use an <code>editor.json</code> file. Output types use a <code>renderer.json</code> file. The <code>"$"</code> root key means “override the UI for the entire type”.</p>
<pre language="json">{
    "editor": {
        "componentOverrides": {
            "$": { "definition": "c/caseInput" }
        }
    }
}
</pre>
<p><b>View the code</b><b>:</b><span style="font-weight: 400"> See the complete</span> <a href="https://github.com/trailheadapps/agent-script-recipes/tree/main/force-app/main/02_actionConfiguration/customLightningTypes/lightningTypes"><span style="font-weight: 400">Lightning Type Bundle files</span></a><span style="font-weight: 400"> in the repository</span></p>
<h2><b>Step 2: Create the agent action asset</b></h2>
<p>The <code>GenAiFunction</code> is the metadata layer that registers your action with Agentforce. Without it, Agentforce cannot resolve your CLT bindings. Every CLT-based action needs a corresponding <code>GenAiFunction</code> in the <code>genAiFunctions</code> folder.</p>
<p>The function metadata XML points to your Apex invocable class:</p>
<pre class="wp-block-code language-xml">&lt;GenAiFunction xmlns="http://soap.sforce.com/2006/04/metadata"&gt;
    &lt;developerName&gt;Submit_Case&lt;/developerName&gt;
    &lt;invocationTarget&gt;CaseSubmissionService&lt;/invocationTarget&gt;
    &lt;invocationTargetType&gt;apex&lt;/invocationTargetType&gt;
    &lt;masterLabel&gt;Submit Case&lt;/masterLabel&gt;
&lt;/GenAiFunction&gt;</pre>
<p>Alongside this XML, you define input and output schema JSON files. These schemas declare the <code>lightning:type</code> for each parameter, which is how the platform knows to look up your Lightning Type Bundle.</p>
<p>The input schema marks <code>case_data</code> as a user input with the CLT type <code>c__caseInput</code>:</p>
<pre language="json">{
    "properties": {
        "case_data": {
            "lightning:type": "c__caseInput",
            "copilotAction:isUserInput": true
        }
    }
}
</pre>
<p>The output schema marks <code>case_result</code> as displayable with the CLT type <code>c__caseResult</code>:</p>
<pre language="json">{
    "properties": {
        "case_result": {
            "lightning:type": "c__caseResult",
            "copilotAction:isDisplayable": true
        }
    }
}
</pre>
<p><span style="font-weight: 400">See the full </span><a href="https://github.com/trailheadapps/agent-script-recipes/tree/main/force-app/main/02_actionConfiguration/customLightningTypes/genAiFunctions/Submit_Case"><span style="font-weight: 400">GenAI Function files</span></a><span style="font-weight: 400"> in the repository.</span></p>
<p><span style="font-weight: 400">You can build the Agent action metadata directly in the Salesforce user interface. </span></p>
<p><span style="font-weight: 400">To do this, navigate from Setup to Agentforce Assets, then select Actions and create a new agent action by following below steps.</span></p>
<ol>
<li style="font-weight: 400"><span style="font-weight: 400">Setup → Agentforce Assets → Click on Actions → Click on New Agent Action</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">Fill in the agent action details like Inputs and Outputs description and data types.</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">Ensure you are setting up the Input Rendering and Output Rendering with the right custom Lightning types</span></li>
</ol>
<p>
			  <span class="postimagessection_specify alignnone size-medium wp-image-206317" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260513112615/image3_5c288a-e1778696801549.png?w=1000" class="postimages" width="1000" height="621" alt="The UI for creating an Agentforce action under Agentforce Assets" />
			  </span>
			</p>
<h2><b>Step 3: Define the action in Agent Script</b></h2>
<p><span style="font-weight: 400">While the following sections cover </span><span style="font-weight: 400">action definition</span><span style="font-weight: 400"> via metadata in detail, the Agentforce Builder UI enforces proper naming constraints automatically and is the recommended starting point for most teams.</span></p>
<p>Everything hinges on the action definition in your Agent Script. Two properties control CLT rendering: <code>complex_data_type_name</code> links a parameter to a Lightning type, and <code>is_user_input</code> or <code>is_displayable</code> tells the platform to render the custom component.</p>
<pre language="yaml">actions:
   submit_case:
      inputs:
         case_data: object
            is_user_input: True
            complex_data_type_name: "c__caseInput"
      outputs:
         case_result: object
            complex_data_type_name: "c__caseResult"
            is_displayable: True
      target: "apex://CaseSubmissionService"
      source: "Submit_Case"
</pre>
<p>Notice the <code>source</code> property at the bottom. This is a critical piece that connects Agent Script to an Agentforce action (represented as <a href="https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_genaifunction.htm"><u><code>GenAiFunction</code></u></a><b> </b>in the metadata as discussed in step 2<b>)</b>. The value <code>“</code><code>Submit_Case</code><code>"</code> must match the developer name of a <code>GenAiFunction</code> metadata file in your project.</p>
<h3><b>Triggering the CLT editor in Agent Script</b></h3>
<p>One detail that is easy to miss: your Agent Script subagent instructions must include the <code>user_input</code><code> </code>keyword when calling the action. This tells the platform to render the CLT editor component instead of collecting input through plain text.</p>
<pre language="yaml">reasoning:
   instructions: -&gt;
      | Call {!@actions.submit_case} action's user_input tool to collect the case details.
</pre>
<p><span style="font-weight: 400">Without this phrase, the platform falls back to text-based input collection. The </span><span style="font-weight: 400">user_input</span><span style="font-weight: 400"> keyword is what activates the entire CLT editor rendering pipeline.</span></p>
<p><b>Important note:</b><span style="font-weight: 400"> In Agent Script the subagent’s action name and the subagent reasoning action name should be exactly the same.</span></p>
<p><b>View the code</b><b>:</b><span style="font-weight: 400"> See the full instructions for the</span> <a href="https://github.com/trailheadapps/agent-script-recipes/blob/main/force-app/main/02_actionConfiguration/customLightningTypes/aiAuthoringBundles/CustomLightningTypes/CustomLightningTypes.agent"><span style="font-weight: 400">Agent Script</span></a><span style="font-weight: 400"> in the repository.</span></p>
<h2><span style="font-weight: 400">The alignment checklist</span></h2>
<p><span style="font-weight: 400">CLTs require precise naming across multiple files. If any link in the chain breaks, the platform silently falls back to the default text UI with no error message. The following table shows what must stay aligned:</span></p>
<table>
<thead>
<tr>
<th><span style="font-weight: 400">What</span></th>
<th><span style="font-weight: 400">Where</span></th>
<th><span style="font-weight: 400">Must Match</span></th>
</tr>
</thead>
<tbody>
<tr>
<td><span style="font-weight: 400">Type name</span></td>
<td><span style="font-weight: 400">Agent Script </span><span style="font-weight: 400">complex_data_type_name</span></td>
<td><span style="font-weight: 400">Lightning type folder name</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">Source name</span></td>
<td><span style="font-weight: 400">Agent Script </span><span style="font-weight: 400">source</span></td>
<td><span style="font-weight: 400">GenAI Function </span><span style="font-weight: 400">developerName</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">Apex class</span></td>
<td><span style="font-weight: 400">Lightning type </span><span style="font-weight: 400">schema.json</span></td>
<td><span style="font-weight: 400">Inner class in your service</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">LWC name</span></td>
<td><span style="font-weight: 400">editor.json</span><span style="font-weight: 400"> or </span><span style="font-weight: 400">renderer.json</span></td>
<td><span style="font-weight: 400">Your LWC component name</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">LWC target</span></td>
<td><span style="font-weight: 400">Meta XML </span><span style="font-weight: 400">targetType</span><span style="font-weight: 400"> / </span><span style="font-weight: 400">sourceType</span></td>
<td><span style="font-weight: 400">Lightning type name</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">Wrapper fields</span></td>
<td><span style="font-weight: 400">Apex request/response classes</span></td>
<td><span style="font-weight: 400">Agent Script action parameter names</span></td>
</tr>
</tbody>
</table>
<p><span style="font-weight: 400">Check these connections first when debugging. The silent fallback behavior makes misalignment hard to spot.</span></p>
<p>
			  <span class="postimagessection_specify alignnone size-medium wp-image-206318" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260513112711/image1_d51cd1-e1778696844677.png?w=1000" class="postimages" width="1000" height="600" alt="User interface for building an agent with custom Lightning types in the new Agentforce Builder to adhere to precise naming conventions" />
			  </span>
			</p>
<h2><span style="font-weight: 400">Conclusion</span></h2>
<p><span style="font-weight: 400">Custom Lightning types bring the power of Lightning Web Components into Agentforce conversations. You can collect precise, validated data through custom forms and present results in rich, branded cards, all without leaving the Agentforce experience.</span></p>
<p><span style="font-weight: 400">The key pieces are the Agent Script action definition and the action in the Agentforce assets, the Lightning Type Bundle, and the LWC components. Each layer has a specific job, and the naming alignment across all four layers is what makes the whole system work.</span></p>
<p><span style="font-weight: 400">This pattern opens up new possibilities for building enterprise-grade agent experiences. Forms with dropdowns and validation, structured result cards with conditional styling, and multistep workflows can all be rendered inline within the conversation.</span></p>
<p><span style="font-weight: 400">The complete working example is available in the </span><a href="https://github.com/trailheadapps/agent-script-recipes"><span style="font-weight: 400">Agent Script Recipes</span></a><span style="font-weight: 400"> repository under the </span><a href="https://github.com/trailheadapps/agent-script-recipes/tree/main/force-app/main/02_actionConfiguration/customLightningTypes"><span style="font-weight: 400">customLightningTypes</span></a><span style="font-weight: 400"> recipe. Clone the repo, deploy to a scratch org or Developer Edition org, and start building your own CLT-powered Agentforce agents.</span></p>
<h2><span style="font-weight: 400">Resources</span></h2>
<ul>
<li style="font-weight: 400"><a href="https://developer.salesforce.com/docs/platform/lightning-types/overview"><span style="font-weight: 400">Lightning Types Developer Guide</span></a></li>
<li style="font-weight: 400"><a href="https://github.com/trailheadapps/agent-script-recipes"><span style="font-weight: 400">Agent Script Recipes Sample App</span></a></li>
<li style="font-weight: 400"><a href="https://developer.salesforce.com/docs/ai/agentforce/guide/agent-script.html"><span style="font-weight: 400">Agent Script Documentation</span></a></li>
</ul>
<h2><span style="font-weight: 400">About the authors</span></h2>
<p><b>Mohith Shrivastava</b><span style="font-weight: 400"> is a Principal Developer Advocate at Salesforce with 15 years of experience building enterprise-scale products on the Agentforce 360 Platform. Mohith is currently among the lead contributors on Salesforce Stack Exchange, a developer forum where Salesforce Developers can ask questions and share knowledge. You can follow him on </span><a href="https://www.linkedin.com/in/mohith-shrivastava-9a36464a/"><span style="font-weight: 400">LinkedIn</span></a><span style="font-weight: 400">.</span></p>
<p><b>Parvinder Singh</b><span style="font-weight: 400"> is a Senior Forward Deployed Engineer at Salesforce with deep expertise in Agentforce and Agent Script, specializing in building intelligent, customized agent experiences for enterprise customers. He is passionate about sharing developer insights with the community and bringing practical, field-tested patterns to life through hands-on content.</span></p>
<p>The post <a href="https://developer.salesforce.com/blogs/2026/05/use-custom-lightning-types-in-agent-script-for-rich-agent-ui">Use Custom Lightning Types in Agent Script for Rich Agent UI</a> appeared first on <a href="https://developer.salesforce.com/blogs">Salesforce Developers Blog</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://developer.salesforce.com/blogs/2026/05/use-custom-lightning-types-in-agent-script-for-rich-agent-ui/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<post-id xmlns="com-wordpress:feed-additions:1">206313</post-id><media:thumbnail url="https://d259t2jj6zp7qm.cloudfront.net/images/20260513110616/Thumbnail_Headshot-2-e1778695588316.png?w=1000" />
<media:content url="https://d259t2jj6zp7qm.cloudfront.net/images/20260513110616/Thumbnail_Headshot-2-e1778695588316.png?w=1000" medium="image" />
	</item>
		<item>
		<title>The New Agentforce Metadata and Development Lifecycle</title>
		<link>https://developer.salesforce.com/blogs/2026/05/new-agentforce-metadata-and-development-lifecycle</link>
		<comments>https://developer.salesforce.com/blogs/2026/05/new-agentforce-metadata-and-development-lifecycle#respond</comments>
		<pubDate>Thu, 14 May 2026 19:55:24 +0000</pubDate>
		<dc:creator><![CDATA[Alba Rivas]]></dc:creator>
				<category><![CDATA[Agentforce]]></category>
		<category><![CDATA[App Development]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Developer Tooling]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Salesforce Releases]]></category>
		<category><![CDATA[Agent Script]]></category>
		<category><![CDATA[alm]]></category>
		<category><![CDATA[CI/CD]]></category>
		<category><![CDATA[GenAiPlannerBundle]]></category>
		<category><![CDATA[Metadata API]]></category>
		<category><![CDATA[salesforce developers]]></category>
		<category><![CDATA[Spring '26]]></category>

		<guid isPermaLink="false">https://developer.salesforce.com/blogs/?p=206288</guid>
		<description><![CDATA[<p>Streamline your CI/CD pipelines by leveraging the new versioned metadata model and human-readable Agent Scripts. Learn how bundleized assets eliminate "global ripples" and simplify peer reviews for more reliable agent deployments.</p>
<p>The post <a href="https://developer.salesforce.com/blogs/2026/05/new-agentforce-metadata-and-development-lifecycle">The New Agentforce Metadata and Development Lifecycle</a> appeared first on <a href="https://developer.salesforce.com/blogs">Salesforce Developers Blog</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p><span style="font-weight: 400">The </span><a href="https://help.salesforce.com/s/articleView?id=ai.agent_builder_intro.htm&amp;type=5"><span style="font-weight: 400">new Agentforce Builder</span></a><span style="font-weight: 400"> (GA Spring &#8217;26) introduces a completely revamped experience for authoring and testing AI agents. It provides a high-velocity, &#8220;safe-to-fail&#8221; environment where you can iterate on complex logic without worrying about breaking your live production agents.</span></p>
<p><span style="font-weight: 400">As a Salesforce developer, you know that a new building experience usually means changes under the hood. To support this faster, safer way of working, the underlying metadata had to evolve. This post walks through the new developer workflow, why the metadata changed, and how to structure your packages for deployment.</span></p>
<h2><b>The new authoring workflow: from script to metadata</b></h2>
<p><span style="font-weight: 400">To understand the metadata changes, it helps to understand the new mental model for building agents. The new Agentforce Builder introduces a clear separation between your &#8220;intent&#8221; (what you want the agent to do) and the engine&#8217;s &#8220;execution&#8221; (the active metadata).</span></p>
<p><span style="font-weight: 400">Here is how the lifecycle works:</span></p>
<ol>
<li><b><span>Write and build:</span></b><span> You author your agent using the Agentforce Builder UI or directly via an </span><b><span>Agent Script</span></b><span>. This human-readable script is saved as a single </span><code><span>.agent</span></code><span> file within a new </span><code><span>AiAuthoringBundle</span></code><span> metadata type, representing your agent’s configuration. At this stage, your work is a draft.</span></li>
<li><b><span>Iterate and preview:</span></b><span> You test your draft using preview modes (like Simulation mode, which safely isolates your tests from org data).</span></li>
<li><b><span>Publish:</span></b><span> When you are happy with the draft, you </span><i><span>commit</span></i><span> your version. </span><b><span>This is the crucial moment.</span></b><span> It is only during commit that the platform translates your </span><code>.agent</code><span> script into the active </span><code>Bot</code><span> and </span><code>GenAiPlannerBundle</code><span> metadata that is actually used to run your agent.</span></li>
</ol>
<h2><b>Why the metadata changed: bundling local assets</b></h2>
<p>So, why did we change the <a href="https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_genaiplannerbundle.htm"><u><code>GenAiPlannerBundle</code><span> metadata</span></u></a><span> structure for this new builder? The answer comes down to isolation and deployment reliability.</span><br />
<span></span></p>
<p><span>Historically, Agentforce assets were global. If you modified a shared subagent for one agent, you triggered a &#8220;global ripple&#8221; that instantly impacted every other agent using that subagent. To solve this, Salesforce introduced </span><b><span>Local Assets</span></b><span> (including local subagents and local actions), which clone a global asset and anchor it specifically to one agent version. Once local, you can edit it safely without breaking anything else.</span><br />
<span></span></p>
<p><span>While Local Assets have been available for a while, the </span><code>GenAiPlannerBundle</code> metadata needed to be updated to fully support them in CI/CD pipelines. Previously, agent metadata was distributed across metadata types. The main change in the new <code>GenAiPlannerBundle</code> is <i>bundleization</i><b>.</b> In short, we restructured the metadata to ensure that <i>all</i> dependent agent assets related to any given version are deployed and available in one centralized folder structure. This prevents deployment errors and ensures your agent has everything it needs to function exactly as it did in preview.</p>
<h2><b>Under the hood: the new metadata structure</b></h2>
<p><span style="font-weight: 400">Instead of scattered files, the directory structure now cleanly encapsulates everything specific to each agent version.</span></p>
<p>
			  <span class="postimagessection_specify alignnone size-medium wp-image-206308" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260513105223/image3_7fea0a.png?w=594" class="postimages" width="594" height="1000" alt="Diagram showing the GenAiPlannerBundle directory structure with planner file, localActions subfolder, and input/output schema.json files" />
			  </span>
			</p>
<p><code>AiAuthoringBundles</code><span> is a directory that contains all the design-time artifacts for the agent. The bundle supports multiple versioned subdirectories (e.g., </span><code>AgentName_1</code><span>, </span><code>AgentName_2</code><span>, etc.), each with its own </span><code>.agent</code><span> file and </span><code>.bundle-meta.xml</code><span> descriptor</span><span>. These correspond to different lifecycle states such as draft and committed versions of the agent. Within each version:</span></p>
<ul>
<li><span>The </span><code>.agent</code><span> file holds the agent&#8217;s configuration written in Agent Script: name, label, description, system instructions, subagent definitions, reasoning instructions, variables, conditionals, and tool/action references.</span></li>
<li><span>The metadata descriptor (</span><code>.bundle-meta.xml)</code><span> declares the bundleType (e.g., AGENT) and the target agent version it points to.</span></li>
</ul>
<p><code><span>Bot</span></code><span> contains information common to all versions of the agent, such as the agent type and useful settings like whether to log private data. It also holds agent-level context variables, which are distinct from the conversation variables that live inside each </span><code><span>BotVersion</span></code><span>. </span><code><span>BotVersion </span></code><span>details include conversation variables, welcome message, and transfer conversation message.</span></p>
<p>
			  <span class="postimagessection_specify alignnone size-medium wp-image-206310" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260513105333/image1_7095ac.png?w=958" class="postimages" width="958" height="626" alt="Diagram showing plannerAction directory content alongside the directory structure of the planner bundle" />
			  </span>
			</p>
<p><code></code><code>GenAiPlannerBundle</code> contains all data relevant to each published version of an agent. Within each version you can find:</p>
<ul>
<li><code>.genAiPlannerBundle</code>, which is the main metadata file containing the agent&#8217;s runtime configuration: subagents, instructions, actions, and orchestration logic.</li>
<li><code>agentGraph</code>, a <code>.json</code> file encoding all transitions and conditions between subagents.</li>
<li><code>agentScript</code>, an encoded copy of the version agent script. This is a snapshot kept for sync-detection purposes, so Agent Builder can tell the user if the script is out of sync with the published/committed metadata.</li>
<li><code>plannerActions</code><span style="color: #4a4a4a;font-family: 'Salesforce Sans', Arial, sans-serif">, agent-level actions (not tied to any specific subagent).</span></li>
<li><code>localActions</code>, subagent-scoped actions, nested under their subagent folder. The <code>input/schema.json</code> and <code>output/schema.json</code> files define the typed parameters for each action.</li>
</ul>
<p>Note: <code>GenAiPlannerBundle</code> versions are auto-incremented in commit order, so they won&#8217;t necessarily match <code>AiAuthoringBundle</code> version numbers.</p>
<p>Remember that both <code>Bot</code> and <code>GenAiPlannerBundle</code> metadata are created automatically when a version is committed, and <code>AiAuthoringBundle</code>, <code>agentScript</code><span>,</span><span> and </span><code>agentGraph</code> are only present on the new Agentforce Builder agent metadata.</p>
<h3><b>Example: </b><b><code>GenAiPlannerBundle</code></b><b> XML</b></h3>
<p><span style="font-weight: 400">When you look at the XML, you&#8217;ll see it now clearly reflects these localized subagents and actions:</span></p>
<pre class="wp-block-code language-xml">&lt;GenAiPlannerBundle&gt;
   &lt;description&gt;New agent description&lt;/description&gt;
   &lt;localTopicLinks&gt;
       &lt;genAiPluginName&gt;Retrieve_data_from_the_Knowledge_Base_16jxx0000001234&lt;/genAiPluginName&gt;
   &lt;/localTopicLinks&gt;
   &lt;localTopics&gt;
       &lt;fullName&gt;Retrieve_data_from_the_Knowledge_Base_16jxx0000001234&lt;/fullName&gt;
       &lt;description&gt;Use the retriever action&lt;/description&gt;
       &lt;pluginType&gt;Topic&lt;/pluginType&gt;
       &lt;masterLabel&gt;Retrieve data from Knowledge Base&lt;/masterLabel&gt;
       &lt;genAiPluginInstructions&gt;
           &lt;description&gt;You are an AI Agent.&lt;/description&gt;
           &lt;sortOrder&gt;1&lt;/sortOrder&gt;
       &lt;/genAiPluginInstructions&gt;
       &lt;localActionLinks&gt;
            &lt;functionName&gt;File_test_retriever_179xx0000001234&lt;/functionName&gt;
       &lt;/localActionLinks&gt;
       &lt;localActions&gt;
           &lt;fullName&gt;File_test_retriever_179xx0000001234&lt;/fullName&gt;
           &lt;invocationTarget&gt;File_test_retriever_1234&lt;/invocationTarget&gt;
           &lt;invocationTargetType&gt;apex:testRetriever&lt;/invocationTargetType&gt;
           &lt;source&gt;File_test_retriever&lt;/source&gt;
       &lt;/localActions&gt;
   &lt;/localTopics&gt;
   &lt;plannerType&gt;AiCopilot__ReAct&lt;/plannerType&gt;
&lt;/GenAiPlannerBundle&gt;</pre>
<p>Each <code>&lt;localTopics&gt;</code> block defines a subagent&#8217;s full configuration: its unique API name, description, plugin type, deterministically ordered instructions, and all the local actions available to it. Optionally, a reference to the source subagent may also be present.</p>
<p>Each <code>&lt;localActions&gt;</code> block defines the action&#8217;s name, master label, invocation target and type, and optionally a <code>source</code> reference to the global action it was cloned from. Additional UX-related settings, such as confirmation behavior and loading text configuration, may also be included.</p>
<h3><b>Sample package.xml with metadata of new model</b></h3>
<p>To successfully retrieve and deploy your agents built with the new Agentforce Builder, ensure your <code>package.xml</code> includes the new bundle types. Below is a sample manifest designed for the Spring ’26 metadata structure.</p>
<pre class="wp-block-code language-xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;Package xmlns="http://soap.sforce.com/2006/04/metadata"&gt;
    &lt;types&gt;
        &lt;members&gt;*&lt;/members&gt;
        &lt;name&gt;GenAiFunction&lt;/name&gt;
    &lt;/types&gt;
    &lt;types&gt;
        &lt;members&gt;*&lt;/members&gt;
        &lt;name&gt;Bot&lt;/name&gt;
    &lt;/types&gt;
    &lt;types&gt;
        &lt;members&gt;*&lt;/members&gt;
        &lt;name&gt;GenAiPlannerBundle&lt;/name&gt;
    &lt;/types&gt;
    &lt;types&gt;
        &lt;members&gt;*&lt;/members&gt;
        &lt;name&gt;GenAiPlugin&lt;/name&gt;
    &lt;/types&gt;
    &lt;types&gt;
        &lt;members&gt;*&lt;/members&gt;
        &lt;name&gt;AiAuthoringBundle&lt;/name&gt;
    &lt;/types&gt;
    &lt;version&gt;66.0&lt;/version&gt;
&lt;/Package&gt;</pre>
<p><span style="font-weight: 400">Note: This manifest uses API version 66.0, which is required to support GenAiPlannerBundle and the new agent metadata types in this example.</span></p>
<h3><b>Developer tips for the new Agentforce Builder</b></h3>
<p><span style="font-weight: 400">Here are two ways to take advantage of development lifecycle improvements enabled by this new architecture:</span></p>
<ul>
<li><b>Use human-readable script files to streamline code reviews.</b> In the legacy Agentforce Builder world, reviewing agent changes meant comparing complex, scattered XML files in your pull requests. Now, you can compare the human-readable <code>.agent</code> script files. This makes peer reviews significantly faster and easier to understand.</li>
<li><b>Use </b><code>AiAuthoringBundle</code><span> </span><b><span>to</span></b><span> </span><b><span>simplify CI/CD.</span></b><span> For most pipelines, you can keep just the </span><code>AiAuthoringBundle</code><span> </span><span><span><span>in your source control. When you need the agent in a new org, you deploy it, version commit to generate the runtime metadata, and finally activate it. This can be done automatically using the following commands:</span></span></span><code>sf project deploy start --metadata AiAuthoringBundle --target-org my-org</code><code>sf agent publish authoring-bundle --api-name MyAuthoringBundle --target-org my-org<br />
</code><code><br />
sf agent activate --api-name MyAuthoringBundle --version 2 --target-org my-org</code>If your team wants a fully automated pipeline with no manual steps, you can maintain both <code>AiAuthoringBundle</code> and <code>GenAiPlannerBundle</code><span> in your source control and deploy them</span> simultaneously, achieving a committed state. The system recognizes the incoming script alongside its pre-realized metadata and skips the manual commit step entirely, so your agent is live immediately after deployment.<code>sf project deploy start --metadata AiAuthoringBundle,GenAiPlannerBundle --target-org my-org</code></li>
</ul>
<h2><b>Conclusion</b></h2>
<p><span style="font-weight: 400">The bundleized metadata structure is what makes the isolated, version-safe authoring possible in the new Agentforce Builder. With it, your metadata is cleaner, your code reviews are easier, and your deployments are more reliable. </span></p>
<p><span style="font-weight: 400">Get started with Agent Script and the new Agentforce Builder by completing </span><a href="https://trailhead.salesforce.com/content/learn/projects/create-an-agent-using-pro-code-tools/create-an-agent-from-your-dx-project"><span style="font-weight: 400">this Trailhead module</span></a><span style="font-weight: 400">, reading more </span><a href="https://developer.salesforce.com/blogs/2026/02/agent-script-decoded-intro-to-agent-script-language-fundamentals"><span style="font-weight: 400">on our blog</span></a><span style="font-weight: 400">, watching our </span><a href="https://www.youtube.com/playlist?list=PLgIMQe2PKPSJNLEQTPkr06gKhjnHgI1Jb"><span style="font-weight: 400">Agent Script decoded playlist on YouTube</span></a><span style="font-weight: 400">, or registering for one of the upcoming </span><a href="https://developer.salesforce.com/events#upcomingevents"><span style="font-weight: 400">Agentforce Builder workshops</span></a><span style="font-weight: 400">.</span></p>
<h2><b>Resources</b></h2>
<ul>
<li style="font-weight: 400"><span style="font-weight: 400">Release Notes:</span>
<ul>
<li style="font-weight: 400"><a href="https://help.salesforce.com/s/articleView?id=ai.agent_versions_lifecycle.htm&amp;type=5"><span style="font-weight: 400">Versioning and Editing Agents</span></a></li>
<li style="font-weight: 400"><a href="https://help.salesforce.com/s/articleView?id=release-notes.rn_einstein_agentforce_versioning_improvements.htm&amp;release=256&amp;type=5"><span style="font-weight: 400">Test and Customize your Agents with Improved Agent Versions</span></a></li>
</ul>
</li>
<li style="font-weight: 400"><span style="font-weight: 400">Help Docs:</span>
<ul>
<li style="font-weight: 400"><a href="https://help.salesforce.com/s/articleView?id=ai.copilot_actions_edit_reference.htm&amp;type=5"><span style="font-weight: 400">Editing Standard Agent Action Reference Actions </span></a></li>
</ul>
</li>
<li style="font-weight: 400"><span style="font-weight: 400">Packaging:</span>
<ul>
<li style="font-weight: 400"><a href="https://developer.salesforce.com/docs/atlas.en-us.pkg2_dev.meta/pkg2_dev/dev2gp_packageable_agentforce_md.htm"><span style="font-weight: 400">Package Agentforce Metadata Components</span></a></li>
<li style="font-weight: 400"><a href="https://developer.salesforce.com/docs/atlas.en-us.pkg2_dev.meta/pkg2_dev/dev2gp_package_agent_templates.htm"><span style="font-weight: 400">Develop and Package Agent Templates Using Scratch Orgs </span></a></li>
</ul>
</li>
<li style="font-weight: 400"><span style="font-weight: 400">Metadata updates:</span>
<ul>
<li style="font-weight: 400"><a href="https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_genaiplannerbundle.htm"><span style="font-weight: 400">GenAiPlannerBundle</span></a></li>
<li style="font-weight: 400"><a href="https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_genaifunction.htm"><span style="font-weight: 400">GenAiFunction</span></a></li>
<li style="font-weight: 400"><a href="https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_genaiplugin.htm"><span style="font-weight: 400">GenAiPlugin</span></a></li>
<li style="font-weight: 400"><a href="https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_genaiplugininstructiondef.htm"><span style="font-weight: 400">GenAiPluginInstructionDef</span></a></li>
</ul>
</li>
</ul>
<p><b>Shreyas</b><span style="font-weight: 400"> is a Lead Software Engineer at Salesforce AI in San Francisco and a Fellow of the Institute of Analytics (FIoA). As a lead member of the Agentforce Core Platform team, he co-designed and led the Agentforce Versioning System and Local Assets Configuration changes to bring enterprise-grade ALM to Agentforce. </span><span style="font-weight: 400">You can follow him on</span> <a href="https://www.linkedin.com/in/rshreyas2/"><span style="font-weight: 400">Linkedin</span></a><span style="font-weight: 400">.</span></p>
<p><b>Alba Rivas</b><span style="font-weight: 400"> works as a Principal Developer Advocate at Salesforce. You can follow her on</span> <a href="https://www.linkedin.com/in/alba-rivas/"><span style="font-weight: 400">Linkedin</span></a><span style="font-weight: 400">.</span></p>
<p>The post <a href="https://developer.salesforce.com/blogs/2026/05/new-agentforce-metadata-and-development-lifecycle">The New Agentforce Metadata and Development Lifecycle</a> appeared first on <a href="https://developer.salesforce.com/blogs">Salesforce Developers Blog</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://developer.salesforce.com/blogs/2026/05/new-agentforce-metadata-and-development-lifecycle/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<post-id xmlns="com-wordpress:feed-additions:1">206288</post-id><media:thumbnail url="https://d259t2jj6zp7qm.cloudfront.net/images/20260514111122/DoubleHeadshot-4-1-e1778782304152.png?w=1000" />
<media:content url="https://d259t2jj6zp7qm.cloudfront.net/images/20260514111122/DoubleHeadshot-4-1-e1778782304152.png?w=1000" medium="image" />
	</item>
		<item>
		<title>Expose Custom Apex as a Hosted MCP Tool for Agents</title>
		<link>https://developer.salesforce.com/blogs/2026/05/expose-custom-apex-as-a-hosted-mcp-tool-for-agents</link>
		<comments>https://developer.salesforce.com/blogs/2026/05/expose-custom-apex-as-a-hosted-mcp-tool-for-agents#respond</comments>
		<pubDate>Wed, 13 May 2026 16:56:25 +0000</pubDate>
		<dc:creator><![CDATA[Mohith Shrivastava]]></dc:creator>
				<category><![CDATA[Agentforce]]></category>
		<category><![CDATA[Apex]]></category>
		<category><![CDATA[APIs and Integrations]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Developer Tooling]]></category>
		<category><![CDATA[New Developments]]></category>
		<category><![CDATA[ai]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Developer Preview]]></category>
		<category><![CDATA[Headless 360]]></category>
		<category><![CDATA[Integrations]]></category>
		<category><![CDATA[MCP]]></category>

		<guid isPermaLink="false">https://developer.salesforce.com/blogs/?p=206291</guid>
		<description><![CDATA[<p>Shift from UI-first to agent-first with Headless 360. Learn how to expose your Apex logic as Salesforce Hosted MCP tools, allowing AI agents like Claude or Cursor to discover and invoke your business intelligence directly via the Model Context Protocol.</p>
<p>The post <a href="https://developer.salesforce.com/blogs/2026/05/expose-custom-apex-as-a-hosted-mcp-tool-for-agents">Expose Custom Apex as a Hosted MCP Tool for Agents</a> appeared first on <a href="https://developer.salesforce.com/blogs">Salesforce Developers Blog</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p><span style="font-weight: 400">Salesforce has always been a business process platform. For over two decades, developers have encoded complex business logic, such as deal scoring, customer segmentation, and approval routing, into Apex classes that power the world’s largest enterprises. But that logic has historically been consumed through Salesforce’s own UI layers: Lightning pages, flows, and Visualforce. The business intelligence lives on the platform, locked behind a browser tab.</span></p>
<p><a href="https://www.salesforce.com/news/stories/salesforce-headless-360-announcement/"><span style="font-weight: 400">Headless 360</span></a><span style="font-weight: 400"> and </span><a href="https://developer.salesforce.com/docs/platform/hosted-mcp-servers/guide"><span style="font-weight: 400">Salesforce Hosted MCP Servers</span></a><span style="font-weight: 400"> introduce a shift from UI-first to agent-first. Every capability on the platform — data access, business logic, automation — becomes consumable through CLIs, APIs, and the </span><a href="https://modelcontextprotocol.io/docs/getting-started/intro"><span style="font-weight: 400">Model Context Protocol (MCP)</span></a><span style="font-weight: 400">, an open standard that lets AI agents discover and call tools hosted on external servers. AI agents running in Slack, Claude, ChatGPT, Cursor, or any MCP-compatible client can now reach into Salesforce and invoke your business logic directly. No login screen. No navigation. No UI at all.</span></p>
<p><span style="font-weight: 400">In this blog post, we’ll show you how to write custom Apex business logic, expose it as a Hosted MCP Server on Salesforce, deploy the necessary metadata to configure authentication, and connect an external AI agent like Claude to invoke your logic.</span></p>
<h2><b>What makes Salesforce Hosted MCP different</b></h2>
<p><span style="font-weight: 400">A Salesforce Hosted MCP Server is a platform-managed endpoint that exposes Apex actions, Apex REST, and external APIs as discoverable tools for AI agents through the Model Context Protocol. Unlike self-hosted MCP servers, it runs on Salesforce infrastructure handling authentication, tool discovery, and request routing without external deployment.</span></p>
<p><span style="font-weight: 400">A Salesforce Hosted MCP tool delivers three things that no raw database can match out-of-the-box: </span></p>
<ul>
<li style="font-weight: 400"><span style="font-weight: 400">Pre-built business object graphs (e.g., Account → Opportunity → Product → Revenue) with relationships already modeled </span></li>
<li style="font-weight: 400"><span style="font-weight: 400">A record-level sharing model that automatically scopes results to what this specific caller is allowed to see </span></li>
<li style="font-weight: 400"><span style="font-weight: 400">Decades of accumulated business process metadata that each customer’s org has already encoded over years of operation</span></li>
</ul>
<h2><b>Example: Pipeline intelligence</b></h2>
<p><span style="font-weight: 400">The example exposes a pipeline intelligence tool built in Apex. An AI agent passes an account name, and the tool returns a complete analysis: open deals with risk levels, weighted pipeline value, product line items, and an overall health assessment.</span></p>
<p>The Apex <code>@InvocableMethod</code> (see <a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_annotation_InvocableMethod.htm"><u>docs</u></a>) that powers flows and Agentforce actions now also serves external AI agents through MCP. Write the logic once; it runs everywhere.</p>
<p>The Apex class uses global access (required for MCP tool discovery) and structures the method as a deep module, absorbing interpretive logic so that the Agent receives insight, not raw data.</p>
<p>The method starts by resolving the account using fuzzy matching: trying an exact name match first, then falling back to a LIKE pattern.</p>
<pre language="apex">global with sharing class AccountPipelineService {
    @InvocableMethod(
        label='Get Account Pipeline'
        description='Returns open opportunities with line items and computed business intelligence (risk levels, weighted pipeline, health summary) for a given account name. Supports fuzzy matching.'
    )
global static List getAccountPipeline(List requests) {
  // All private methods is invoked here..
}
private static Account resolveAccount(String accountName, PipelineResult result) {
     List accounts = [
         SELECT Id, Name, Industry, AnnualRevenue
         FROM Account
         WHERE Name = :accountName
         WITH USER_MODE
         LIMIT 1
     ];

     if (!accounts.isEmpty()) {
         result.matchType = 'exact';
         return accounts[0];
     }

     String fuzzyPattern = '%' + accountName + '%';
     accounts = [
         SELECT Id, Name, Industry, AnnualRevenue
         FROM Account
         WHERE Name LIKE :fuzzyPattern
         WITH USER_MODE
         LIMIT 1
     ];

     if (!accounts.isEmpty()) {
         result.matchType = 'partial';
         return accounts[0];
     }

     result.accountFound = false;
     result.message = 'No account found matching: ' + accountName;
     return null;
 }

}

</pre>
<p>When no account matches, the tool returns a structured response with <code>accountFound: false</code> and a descriptive message, giving the AI agent a clear signal to ask the user for clarification rather than failing silently.</p>
<p>Once the account is resolved, a single SOQL query traverses the full business object graph.</p>
<pre language="apex">List opportunities = [
     SELECT Id, Name, Amount, StageName, Probability, CloseDate,
         Owner.Name,
         (SELECT Id, Product2.Name, Quantity, UnitPrice, TotalPrice
          FROM OpportunityLineItems)
     FROM Opportunity
     WHERE AccountId = :acc.Id
         AND IsClosed = false
     WITH USER_MODE
     ORDER BY Amount DESC NULLS LAST
 ];
</pre>
<p><span style="font-weight: 400">Each deal is then scored for risk based on probability and proximity to close date.</span></p>
<pre language="apex">private static String assessRisk(Decimal probability, Integer daysUntilClose) {
     if (daysUntilClose &lt;= 30 &amp;&amp; (probability == null || probability &lt; 60)) {
         return 'High';
     }
     if (probability == null || probability &lt; 50) {
         return 'Medium';
     }
     return 'Low';
 }</pre>
<p>The overall pipeline health is a multi-factor assessment combining high-risk ratio and weighted conversion strength.</p>
<pre language="apex">private static String assessPipelineHealth(
     Integer totalDeals, Integer highRiskCount,
     Decimal weightedValue, Decimal totalValue
 ) {
     if (totalDeals == 0) {
         return 'Empty — no open deals';
     }
     Decimal highRiskRatio = (Decimal) highRiskCount / totalDeals;
     Decimal conversionStrength = totalValue &gt; 0 ? weightedValue / totalValue : 0;

     if (highRiskRatio &gt; 0.5) {
         return 'Weak — majority of deals are high risk';
     }
     if (conversionStrength &lt; 0.4) {
         return 'At Risk — low weighted conversion across pipeline';
     }
     if (highRiskRatio &lt;= 0.2 &amp;&amp; conversionStrength &gt;= 0.6) {
         return 'Strong — high confidence, low risk';
     }
     return 'Moderate — mixed signals, review recommended';
 }
</pre>
<p>Key design decisions:</p>
<ul>
<li><b>Fuzzy matching</b>: The tool resolves partial account names (“Acme” finds “Acme Corporation”), reducing errors for AI agents that may not know exact names.</li>
<li><b>Computed fields</b>: <code>riskLevel</code>, <code>weightedPipelineValue</code>, and <code>pipelineHealthSummary</code><span> </span><span>are calculated inside the method. The AI agent never needs to interpret raw probabilities or close dates.</span></li>
<li><b><code>WITH USER_MODE</code></b>: SOQL queries enforce the running user’s field-level and object-level security automatically.</li>
<li><b style="color: #4a4a4a;font-family: 'Salesforce Sans', Arial, sans-serif">Cross-object traversal</b><span style="color: #4a4a4a;font-family: 'Salesforce Sans', Arial, sans-serif">: This is a single tool call that spans Account, Opportunity, OpportunityLineItem, Product2, and User.</span></li>
</ul>
<h2><b>Registering the Hosted MCP Server</b></h2>
<p><span style="font-weight: 400">With the Apex class deployed, the next step is the MCP Server Definition, the metadata that maps your Apex action to a named tool and controls how AI agents discover it.</span></p>
<p><span style="font-weight: 400">Below is an example deployable metadata for registering the hosted MCP server. The metadata can be source controlled and CI/CD deployed alongside the Apex class.</span></p>
<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;McpServerDefinition xmlns="http://soap.sforce.com/2006/04/metadata"&gt;
    &lt;description&gt;Analyzes account pipeline health with deal risk scoring
    and weighted forecasts by traversing Salesforce's native business
    object graph.&lt;/description&gt;
    &lt;masterLabel&gt;Pipeline Intelligence&lt;/masterLabel&gt;
    &lt;tools&gt;
        &lt;apiDefinition&gt;
            &lt;apiIdentifier&gt;aa:apex-AccountPipelineService&lt;/apiIdentifier&gt;
            &lt;apiSource&gt;API_CATALOG&lt;/apiSource&gt;
            &lt;operation&gt;AccountPipelineService&lt;/operation&gt;
        &lt;/apiDefinition&gt;
        &lt;descriptionOverride&gt;Returns open opportunities with line items
        and computed business intelligence (risk levels, weighted pipeline,
        health summary) for a given account name.
        Supports fuzzy matching.&lt;/descriptionOverride&gt;
        &lt;toolName&gt;getAccountPipeline&lt;/toolName&gt;
        &lt;toolTitle&gt;Get Account Pipeline&lt;/toolTitle&gt;
    &lt;/tools&gt;
&lt;/McpServerDefinition&gt;</pre>
<p><span style="font-weight: 400">Note: MCP Registration can also be done via Salesforce User Interface. The steps are documented in the official </span><a href="https://help.salesforce.com/s/articleView?language=en_US&amp;id=platform.api_catalog_manage_mcp_servers.htm&amp;type=5"><span style="font-weight: 400">documentation</span></a><span style="font-weight: 400">.</span></p>
<h3><b>Why every field here matters</b></h3>
<p>AI agents don’t read your code. When an MCP client calls <code>tools/list</code>, the agent sees exactly four things per tool: a name, a description, an <code>inputSchema</code>, and an <code>outputSchema</code>. That’s the entire basis for deciding whether to call your tool, what to pass, and how to interpret the response.</p>
<p>Each metadata field controls part of that picture.</p>
<table>
<tbody>
<tr>
<td><b>Metadata Field</b></td>
<td><b>Maps To</b></td>
<td><b>Role</b></td>
</tr>
<tr>
<td><span style="font-weight: 400">toolName</span></td>
<td><span style="font-weight: 400">MCP name</span></td>
<td><span style="font-weight: 400">Identifier that the agent uses to invoke the tool.</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">descriptionOverride</span></td>
<td><span style="font-weight: 400">MCP description</span></td>
<td>The tool’s pitch — drives whether the agent selects it. Falls back to <code>@InvocableMethod</code> description if empty.</td>
</tr>
<tr>
<td><span style="font-weight: 400">apiDefinition</span></td>
<td><span style="font-weight: 400">MCP inputSchema + outputSchema</span></td>
<td>Points to the API Catalog entry. Salesforce generates both JSON Schemas from your <code>@InvocableVariable</code> annotations.</td>
</tr>
<tr>
<td><span style="font-weight: 400">description (server-level)</span></td>
<td><span style="font-weight: 400">Server description</span></td>
<td><span style="font-weight: 400">Helps agents decide whether to explore this server’s tools at all.</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">toolTitle</span></td>
<td><span style="font-weight: 400">Display label</span></td>
<td><span style="font-weight: 400">Human-readable name in client UIs. Not used for tool selection.</span></td>
</tr>
</tbody>
</table>
<h3><b>From Apex annotations to agent-readable schemas</b></h3>
<p>The <code>apiDefinition</code> is the bridge. It references the API Catalog entry auto-created from your global class. Salesforce reads the <code>@InvocableVariable</code> annotations on your input and output classes and generates the <code>inputSchema</code> and <code>outputSchema</code> that agents see.</p>
<pre language="apex">// Input class → becomes inputSchema (wrapped in an inputs[] array)
 @InvocableVariable(required=true description='The name of the Account to look up pipeline for. Supports partial matching.')
 global String accountName;

 // Output class → becomes outputSchema (nested inside a response envelope as outputValues)
 @InvocableVariable(description='Overall pipeline health: Strong, Moderate, At Risk, or Weak')
 global String pipelineHealthSummary;

 @InvocableVariable(description='Pipeline value weighted by probability — realistic expected revenue')
 global Decimal weightedPipelineValue;
</pre>
<p>The <code>description</code> text you write in each <code>@InvocableVariable</code> annotation becomes the documentation that the agent reads. Without it, the agent sees field types but not meaning. Write them with the agent as your audience for example:</p>
<ul>
<li><b>Input fields</b>: What to provide. “Supports partial matching” tells the agent it doesn’t need an exact name.</li>
<li><b>Output fields</b>: How to interpret. “Negative means overdue” on <code>daysUntilClose</code> prevents misreading.</li>
<li><b>Enumerated values</b>: List them. “Strong, Moderate, At Risk, or Weak” — no guessing.</li>
</ul>
<h3><b>Writing an effective </b><b><code>descriptionOverride</code></b></h3>
<p>The <code>descriptionOverride</code> drives tool selection for the Agent. A good description answers three questions:</p>
<ol>
<li style="font-weight: 400"><b>What does it return?</b><span style="font-weight: 400">  “Returns open opportunities with line items and computed business intelligence (risk levels, weighted pipeline, health summary)”</span></li>
<li style="font-weight: 400"><b>What input does it need?</b><span style="font-weight: 400">  “For a given account name”</span></li>
<li style="font-weight: 400"><b style="color: #4a4a4a;font-family: 'Salesforce Sans', Arial, sans-serif">Any behavioral nuances?</b><span style="font-weight: 400">  “Supports fuzzy matching”</span></li>
</ol>
<h4><b>Anti-patterns to avoid:</b></h4>
<ol>
<li><b>Too vague: </b><span style="font-weight: 400">A description like “Gets pipeline data” gives the agent no signal about what makes this tool different from a generic query tool. The agent is unlikely to select it when multiple tools are available</span></li>
<li><b>Too implementation-focused: </b><span style="font-weight: 400">A description like “Executes SOQL against Opportunity with USER_MODE” tells the agent how the tool is built rather than what it delivers. The agent needs to know what business value the tool provides, not the internal mechanics.</span></li>
<li><b>Missing input guidance: </b><span style="font-weight: 400">If the description does not mention that the tool expects an account name, the agent has no way to know whether it should pass an account ID, an opportunity name, or something else entirely.</span></li>
</ol>
<h3><b>Activate the MCP Servers</b></h3>
<p><span style="font-weight: 400">After deploying, verify the server appears in </span><b>Setup → MCP Servers</b><span style="font-weight: 400"> and activate it. The server must be active before any MCP client can connect.</span></p>
<h2><b>Setting up the External Client App</b></h2>
<p><span style="font-weight: 400">For an MCP client like Claude to authenticate, an External Client App with OAuth is required. This is configured through Setup as follows:</span></p>
<ol>
<li style="font-weight: 400"><span style="font-weight: 400">Navigate to </span><b>Setup → External Client App Manager → New External Client App</b></li>
<li style="font-weight: 400"><span style="font-weight: 400">Provide a label, description, and contact email</span></li>
<li style="font-weight: 400">Enable <b style="color: #4a4a4a;font-family: 'Salesforce Sans', Arial, sans-serif">OAuth</b><span style="font-weight: 400"> with the following settings:</span></li>
</ol>
<table>
<tbody>
<tr>
<td><b>Setting</b></td>
<td><b>Value</b></td>
</tr>
<tr>
<td><span style="font-weight: 400">Callback URL</span></td>
<td><span style="font-weight: 400">https://claude.ai/api/mcp/auth_callback</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">OAuth Scopes</span></td>
<td><span style="font-weight: 400">mcp_api, refresh_token</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">JWT-based access tokens</span></td>
<td><span style="font-weight: 400">Enabled</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">PKCE</span></td>
<td><span style="font-weight: 400">Required</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">All other security options</span></td>
<td><span style="font-weight: 400">Unchecked</span></td>
</tr>
</tbody>
</table>
<p><span style="font-weight: 400">Once saved, the Consumer Key becomes available under </span><b>Settings → Consumer Key and Secret</b><span style="font-weight: 400">. This is the client identifier that Claude uses to initiate the OAuth flow.</span></p>
<p><span style="font-weight: 400">Note: External Client Apps can take up to 30 minutes to become fully active after creation. If Claude’s connection fails immediately after setup, wait and retry.</span></p>
<h2><b>Connecting Claude</b></h2>
<p><span style="font-weight: 400">Connecting Claude to a Hosted MCP Server requires a server URL and an OAuth Client ID — nothing else.</span></p>
<ol>
<li style="font-weight: 400"><span style="font-weight: 400">In </span><a href="http://claude.ai"><span style="font-weight: 400">Claude.ai</span></a><span style="font-weight: 400"> on the web, navigate to </span><b>Settings → Connectors → Add custom connector</b><span style="font-weight: 400"><span style="font-weight: 400"><span style="font-weight: 400">.</span></span></span>Note this assumes you have a Claude account and you are signed in. If you are signed in you can also <a href="https://claude.ai/settings/connectors?modal=add-custom-connector">directly add a connector</a>.</li>
<li style="font-weight: 400"><span style="font-weight: 400">Copy the </span><b>Server URL</b><span style="font-weight: 400"> from Salesforce Setup:</span></li>
</ol>
<ul>
<li style="font-weight: 400"><span style="font-weight: 400">Navigate to </span><b>Setup → Integrations → MCP Servers</b></li>
<li style="font-weight: 400"><span style="font-weight: 400">Click the </span><b>MCP Server name</b><span style="font-weight: 400"> (e.g., “Pipeline Intelligence”)</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">Under </span><b>Authentication Details</b><span style="font-weight: 400">, copy the </span><b>Server URL</b></li>
</ul>
<p><span style="font-weight: 400">The URL follows the pattern below:</span></p>
<table>
<tbody>
<tr>
<td><b>Org Type</b></td>
<td><b>URL Pattern</b></td>
</tr>
<tr>
<td><span style="font-weight: 400">Sandbox / Scratch</span></td>
<td><span style="font-weight: 400">https://api.salesforce.com/platform/mcp/v1/sandbox/custom/{MCP_SERVER_API_NAME}</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">Production / Developer Edition</span></td>
<td><span style="font-weight: 400">https://api.salesforce.com/platform/mcp/v1/custom/{MCP_SERVER_API_NAME}</span></td>
</tr>
</tbody>
</table>
<p><span style="font-weight: 400">For this project, the URL is </span><a href="https://api.salesforce.com/platform/mcp/v1/sandbox/Pipeline_Intelligence"><span style="font-weight: 400">https://api.salesforce.com/platform/mcp/v1/sandbox/Pipeline_Intelligence</span></a></p>
<p><span style="font-weight: 400">Note: You can also copy this from the user interface by navigating to the following: </span></p>
<ol>
<li style="font-weight: 400"><span style="font-weight: 400">Set the </span><b>Server UR</b><span style="font-weight: 400">L in Claude by pasting the URL from Step 2</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">Paste the </span><b>OAuth Consumer Key </b><span style="font-weight: 400">from the External Client App settings</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">Click </span><b>Connect</b><span style="font-weight: 400"> and authenticate with the Salesforce org credentials</span></li>
</ol>
<p><span style="font-weight: 400">Once connected, Claude can invoke the tool naturally:</span></p>
<blockquote><p><span style="font-weight: 400">“What’s happening with Acme’s pipeline?”</span></p></blockquote>
<p><span style="font-weight: 400">The response includes the matched account, open deals with per-deal risk levels, weighted pipeline value, product line items, and an overall health assessment — all computed by the Apex running on Salesforce, all respecting the user’s security context.</span></p>
<p>
			  <span class="postimagessection_specify alignnone size-medium wp-image-206297" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260513085745/image1_c35b5c-e1778687878862.png?w=1000" class="postimages" width="1000" height="625" alt="Claude invoking Salesforce Hosted MCP built with Apex" />
			  </span>
			</p>
<p><span style="font-weight: 400">Note: If you are having issues connecting to MCP servers refer to the troubleshooting section in the </span><a href="https://developer.salesforce.com/docs/platform/hosted-mcp-servers/guide/troubleshooting-overview.html"><span style="font-weight: 400">official docs</span></a><span style="font-weight: 400">.</span></p>
<h2><b>The Headless 360 shift</b></h2>
<p><span style="font-weight: 400">For Apex developers, Headless 360 is a fundamental shift in how you design code. The consumer is no longer a human clicking through a UI; it’s an AI agent that reads tool descriptions, passes structured inputs, and reasons over structured outputs.</span></p>
<p><span style="font-weight: 400">Designing for agents means returning computed insight (not raw fields), writing precise descriptions (not UI labels), and building tools that are self-contained (not steps in a wizard).</span></p>
<p><span style="font-weight: 400">For AI developers exploring MCP, Salesforce is a uniquely deep server: a pre-modeled business graph, governed security, and computed intelligence — not just another database behind an API.</span></p>
<h2><b>A note on tool governance</b></h2>
<p><span style="font-weight: 400">Too many MCP tools overwhelm AI agents, they struggle to pick the right one, leading to irrelevant calls or confused responses. As more teams expose Apex logic as MCP tools, governance becomes important. The Salesforce </span><a href="https://developer.salesforce.com/docs/platform/hosted-mcp-servers/guide/best-practices.html"><span style="font-weight: 400">Hosted MCP Servers Best Practices</span></a><span style="font-weight: 400"> guide recommends keeping tools self-contained (each returns a useful result on its own), avoiding both over-granular tools that require prescribed sequences and over-broad tools that bundle unrelated operations. Give each tool</span></p>
<h2><b>Get started</b></h2>
<p><span style="font-weight: 400">The complete source code for this blog post, setup scripts, and sample data are available on GitHub:</span><a href="https://github.com/msrivastav13/headless-apex-mcp-tool"> <span style="font-weight: 400">headless-apex-mcp-tool</span></a><span style="font-weight: 400">. </span></p>
<p><span style="font-weight: 400">While this post demonstrates the connection with Claude, MCP is an open protocol. Any MCP-compatible agent — Slack, ChatGPT, or your own custom agent — can connect to the same Hosted MCP Server using the same URL and OAuth flow. Check the resources below to learn more.</span></p>
<h2><b>Resources</b></h2>
<ul>
<li style="font-weight: 400"><a href="https://developer.salesforce.com/docs/platform/hosted-mcp-servers/guide/client-connection-overview.html"><span style="font-weight: 400">Connect MCP Clients</span></a></li>
<li style="font-weight: 400"><a href="https://developer.salesforce.com/docs/platform/hosted-mcp-servers/guide/create-external-client-app.html"><span style="font-weight: 400">External Client App Setup for MCP</span></a></li>
<li style="font-weight: 400"><a href="https://developer.salesforce.com/docs/platform/hosted-mcp-servers/guide/claude.html"><span style="font-weight: 400">Connecting Claude to Salesforce MCP</span></a></li>
<li style="font-weight: 400"><a href="https://developer.salesforce.com/docs/platform/hosted-mcp-servers/guide/custom-servers.html"><span style="font-weight: 400">Hosted MCP Servers Developer Guide</span></a></li>
<li style="font-weight: 400"><a href="https://github.com/msrivastav13/headless-apex-mcp-tool"><span style="font-weight: 400">GitHub: Headless Apex MCP Tool</span></a></li>
</ul>
<h2><span style="font-weight: 400">About the author</span></h2>
<p><b>Mohith Shrivastava</b><span style="font-weight: 400"> is a Principal Developer Advocate at Salesforce with 15 years of experience building enterprise-scale products on the Agentforce 360 Platform. Mohith is currently among the lead contributors on Salesforce Stack Exchange, a developer forum where Salesforce Developers can ask questions and share knowledge. You can follow him on </span><a href="https://www.linkedin.com/in/mohith-shrivastava-9a36464a/"><span style="font-weight: 400">LinkedIn</span></a><span style="font-weight: 400">.</span></p>
<p>The post <a href="https://developer.salesforce.com/blogs/2026/05/expose-custom-apex-as-a-hosted-mcp-tool-for-agents">Expose Custom Apex as a Hosted MCP Tool for Agents</a> appeared first on <a href="https://developer.salesforce.com/blogs">Salesforce Developers Blog</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://developer.salesforce.com/blogs/2026/05/expose-custom-apex-as-a-hosted-mcp-tool-for-agents/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<post-id xmlns="com-wordpress:feed-additions:1">206291</post-id><media:thumbnail url="https://d259t2jj6zp7qm.cloudfront.net/images/20260512151244/SingleHeadshot-e1778623995941.png?w=1000" />
<media:content url="https://d259t2jj6zp7qm.cloudfront.net/images/20260512151244/SingleHeadshot-e1778623995941.png?w=1000" medium="image" />
	</item>
		<item>
		<title>AgentLens: Debug Agentforce with Interactive Visualizations</title>
		<link>https://developer.salesforce.com/blogs/2026/05/agentlens-debug-agentforce-with-interactive-visualizations</link>
		<comments>https://developer.salesforce.com/blogs/2026/05/agentlens-debug-agentforce-with-interactive-visualizations#respond</comments>
		<pubDate>Tue, 12 May 2026 17:20:37 +0000</pubDate>
		<dc:creator><![CDATA[Mohith Shrivastava]]></dc:creator>
				<category><![CDATA[Agentforce]]></category>
		<category><![CDATA[App Development]]></category>
		<category><![CDATA[Developer Tooling]]></category>
		<category><![CDATA[Agent Script]]></category>
		<category><![CDATA[Agent Script Decoded]]></category>
		<category><![CDATA[AgentLens]]></category>
		<category><![CDATA[LLM]]></category>

		<guid isPermaLink="false">https://developer.salesforce.com/blogs/?p=206274</guid>
		<description><![CDATA[<p>Debug subagent routing and orchestration in minutes using AgentLens, a free open source tool that visualizes Agentforce agent traces as interactive graphs, FSM diagrams, and step-by-step instructors.</p>
<p>The post <a href="https://developer.salesforce.com/blogs/2026/05/agentlens-debug-agentforce-with-interactive-visualizations">AgentLens: Debug Agentforce with Interactive Visualizations</a> appeared first on <a href="https://developer.salesforce.com/blogs">Salesforce Developers Blog</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p><a href="https://github.com/msrivastav13/AgentLens"><span style="font-weight: 400">AgentLens</span></a><span style="font-weight: 400"> is an open source tool that transforms Agentforce traces into interactive visualizations, such as agent graphs, finite state machine (FSM) diagrams, and step-by-step execution inspectors, so you can debug </span><a href="https://developer.salesforce.com/blogs/2026/02/agent-script-decoded-intro-to-agent-script-language-fundamentals"><span style="font-weight: 400">Agent Script</span></a><span style="font-weight: 400"> orchestration in minutes. It has zero dependencies, runs entirely offline, and keeps all trace data on your machine.</span></p>
<p><span style="font-weight: 400">I built AgentLens when I was writing </span><a href="https://developer.salesforce.com/sample-apps/agent-script-recipes"><span style="font-weight: 400">Agent Script recipes</span></a><span style="font-weight: 400">, the declarative definitions that control how Agentforce route, respond, and invoke tools. I needed a way to quickly debug what my agents were doing during execution in order to build a clear mental model of their orchestration. Whether I was reviewing agent behavior, or instructing a coding agent like Agentforce Vibes or Claude Code to modify Agent Script, I needed to understand the flow. Which subagents talked to each other? What does the state machine look like inside each one of these subagents? Where do handoffs happen, and why?.</span></p>
<p><span style="font-weight: 400">Agentforce already provides a powerful</span> <a href="https://help.salesforce.com/s/articleView?id=ai.generative_ai_platform_trace.htm&amp;type=5"><span style="font-weight: 400">agent platform tracing capabilities</span></a><span style="font-weight: 400">. Every execution is captured — subagent routing, LLM calls, tool invocations, variable mutations, all of it. That trace data is rich and complete, but what was missing for me was a fast, intuitive way to visualize it. I wanted a tool that would allow me to build a mental model in minutes, so I could describe orchestration clearly to a coding agent, judge whether its output was correct, or spot patterns in how my Agentforce agents behave.</span></p>
<p><span style="font-weight: 400">That’s why I built</span><a href="https://github.com/msrivastav13/AgentLens"> <b>AgentLens</b></a><span style="font-weight: 400">.</span></p>
<h2><b>How Agentforce orchestration works (and why it matters for debugging)</b></h2>
<p><span style="font-weight: 400">Before diving into the tool, it helps to understand the two core structures that define how an Agentforce agent executes.</span></p>
<p><span style="font-weight: 400">An Agentforce agent is composed of </span><a href="https://help.salesforce.com/s/articleView?id=ai.agent_topics_parent.htm&amp;type=5"><b>subagents</b></a><span style="font-weight: 400">, and each is responsible for a specific capability, such as order lookup, case routing, or knowledge retrieval for an order management agent. When a user sends a message, the orchestrator decides which subagent should handle the request and hands off the conversation. That subagent may invoke another in turn. The result is a</span><a href="https://en.wikipedia.org/wiki/Directed_acyclic_graph"> <span style="font-weight: 400">directed acyclic graph (DAG)</span></a><span style="font-weight: 400">, a network of subagents connected by handoff edges, where each edge represents one subagent passing control to another. Understanding this DAG tells you </span><i><span style="font-weight: 400">which subagent</span></i><span style="font-weight: 400"> participated in a conversation and </span><i><span style="font-weight: 400">in what order</span></i><span style="font-weight: 400">.</span></p>
<p>
			  <span class="postimagessection_specify alignnone size-medium wp-image-206278" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260511135554/Agent-Graph-in-AgentLens-showing-subagent-nodes-connected-by-directed-handoff-edges-e1778532968283.png?w=1000" class="postimages" width="1000" height="647" alt="Agent Graph in AgentLens showing subagent nodes connected by directed handoff edges" />
			  </span>
			</p>
<p><span style="font-weight: 400">Inside each subagent, execution follows a</span><a href="https://en.wikipedia.org/wiki/Finite-state_machine"> <span style="font-weight: 400">finite-state machine (FSM)</span></a><span style="font-weight: 400">, a sequence of states connected by transitions. The subagent moves from state to state; it might start by calling the LLM, transition to a tool execution based on the LLM’s decision, then transition to a response or hand off to another subagent. Each state has defined transitions that determine what happens next. Understanding the FSM helps you see not just what a subagent did, but how it made decisions at each step: which tools it invoked, why transitions occurred, and where execution paths diverged.</span></p>
<p>
			  <span class="postimagessection_specify alignnone size-medium wp-image-206281" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260511140643/Finite-state-machine-in-AgentLens-e1778533616700.png?w=1000" class="postimages" width="1000" height="647" alt="Finite-state machine in AgentLens" />
			  </span>
			</p>
<p><span style="font-weight: 400">When you’re debugging an Agentforce agent — or prompting a coding agent to fix one — you’re ultimately trying to answer two questions: </span></p>
<ol>
<li style="font-weight: 400"><span style="font-weight: 400">“Did the right subagents get involved, in the right order?” (the DAG) </span></li>
<li style="font-weight: 400"><span style="font-weight: 400">“Did each subagent behave correctly internally?” (the FSM) </span></li>
</ol>
<p><span style="font-weight: 400">The first tells you how the orchestration flowed across the system. The second tells you how decisions were made within each subagent. AgentLens makes both visible.</span></p>
<h2><b>Visualize agent orchestration at three levels</b></h2>
<p><span style="font-weight: 400">AgentLens takes a single Agentforce trace JSON file and presents three connected views, each one level deeper than the last.</span></p>
<p><b>Agent Graph (the DAG)</b><span style="font-weight: 400">: See which subagents communicated and in what order. Each node is a subagent, and each edge is a handoff. The graph shows you the full routing path that the conversation took, making it easy to spot unexpected routing, circular handoffs, or subagents that never got invoked when they should have been.</span></p>
<p><b>Finite-State Machine Diagram</b><span style="font-weight: 400">: Pick any subagent and see its internal execution as an interactive FSM. Nodes are color-coded: blue for LLM calls, teal for tool executions, green for responses. Each arrow is a state transition. Backward arrows reveal retries and loops — places where the subagent repeated a step, usually because a tool returned unexpected results or the LLM needed another pass. This is what tells you </span><i><span style="font-weight: 400">how</span></i><span style="font-weight: 400"> a subagent made its decisions, and it’s what you describe to a coding agent when you want it to change the behavior.</span></p>
<p><span style="font-weight: 400">In one of my recipes, the FSM showed the Routing subagent handing off to Fulfillment four times in a loop. The backward arrow made the pattern obvious: the handoff condition was matching too broadly. I described the FSM to Agentforce Vibes, and it tightened the guard clause in seconds.</span></p>
<p><b>Step-by-Step Trace Inspector</b><span style="font-weight: 400">: Walk through every agent execution event in sequence: the exact system prompt the model received, what it responded to, tool inputs and outputs, and variable diffs showing what changed. Use the arrow keys to navigate and handoffs automatically jump to the next agent, so you never lose the thread.</span></p>
<p>
			  <span class="postimagessection_specify alignnone size-medium wp-image-206285" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260511144735/Step-by-step-tracing-via-AgentLens_F.gif?w=800" class="postimages" width="800" height="517" alt="Step-by-step tracing via AgentLens" />
			  </span>
			</p>
<p><span style="font-weight: 400">Filter controls let you toggle the visibility of variable updates, reasoning steps, enabled tools, and internal system variables. Show only what matters for the question you’re asking.</span></p>
<h2><b>Debug Agent Script in VS Code or your browser</b></h2>
<p><span style="font-weight: 400">Analyzing Agentforce execution traces is the best way to understand its internal decision-making process. Let&#8217;s look at how you can easily visualize and debug these traces with AgentLens.</span></p>
<p><b>VS Code Extension</b><span style="font-weight: 400">: Search for </span><b>AgentLens Visualizer</b><span style="font-weight: 400"> in the Extensions panel or install it from the</span><a href="https://marketplace.visualstudio.com/items?itemName=MohithShrivastava.agentlens-viewer"> <span style="font-weight: 400">VS Code Marketplace</span></a><span style="font-weight: 400">. Once installed, right-click any trace JSON and select </span><b>Open with AgentLens</b><span style="font-weight: 400">. You can still search for </span><b>AgentLens Visualizer</b><span style="font-weight: 400"> in Cursor or other IDEs, since the extension is available on the </span><a href="https://open-vsx.org/extension/msrivastav13/agentlens-viewer"><span style="font-weight: 400">Open VSX Registry</span></a><span style="font-weight: 400">.</span></p>
<p>If your traces live at <code>.sfdx/agents/**/traces/*.json</code> (the default location used by the Salesforce CLI), the extension automatically adds an inline <b>Open in AgentLens</b> CodeLens at the top of the file. AgentLens also integrates with your VS Code theme, with support for light, dark, and high-contrast modes.</p>
<p><b>Web App</b><span style="font-weight: 400">: Head to</span><a href="https://msrivastav13.github.io/AgentLens/"> <span style="font-weight: 400">msrivastav13.github.io/AgentLens</span></a><span style="font-weight: 400">, paste or upload a trace, and you’ll immediately see the agent graph — no install needed. </span></p>
<p><span style="font-weight: 400">For full offline use, download the index.html from the</span><a href="https://github.com/msrivastav13/AgentLens"> <span style="font-weight: 400">GitHub repo</span></a><span style="font-weight: 400">, open it in your browser, and paste the trace JSON from Agentforce Builder. Everything runs locally on your machine, and no trace data leaves your environment.</span></p>
<h3><b>Where do Agentforce traces come from?</b></h3>
<p><span style="font-weight: 400">You can export traces from several places in the Agentforce ecosystem:</span></p>
<ul>
<li><b>SF CLI</b>: Run <code>sf agent preview -o &lt;org&gt;</code>. Traces save to .sfdx/agents/ in your project.</li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=salesforce.salesforcedx-vscode-agents"><b><u>Agentforce DX Extension</u></b></a>: Copy the plan response JSON directly from the trace viewer.</li>
<li><b>Agentforce Builder</b>: Run a conversation in the preview panel, then copy the trace JSON from conversation details.</li>
</ul>
<p><span style="font-weight: 400">The screenshot below shows how to copy trace JSON from the Agentforce Builder trace panel.</span></p>
<p>
			  <span class="postimagessection_specify alignnone size-medium wp-image-206279" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260511140516/Copy-trace-logs-for-AgentLens-in-Agentforce-Builder-e1778533530374.png?w=1000" class="postimages" width="1000" height="625" alt="Copy trace logs for AgentLens in Agentforce Builder" />
			  </span>
			</p>
<p><span style="font-weight: 400">Once you’ve copied the trace, simply paste it into the </span><a href="https://msrivastav13.github.io/AgentLens/"><span style="font-weight: 400">AgentLens</span></a><span style="font-weight: 400"> user interface to visualize the agent graph and step through the execution trace interactively. The screenshot below shows how AgentLens transforms the raw JSON copied from Agentforce Builder into an interactive debugging experience.</span></p>
<p>
			  <span class="postimagessection_specify alignnone size-medium wp-image-206280" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260511140546/AgentLens-web-application-converting-trace-JSON-into-an-interactive-debugger-e1778533559242.png?w=1000" class="postimages" width="1000" height="632" alt="AgentLens web application converting trace JSON into an interactive debugger" />
			  </span>
			</p>
<h2><span style="font-weight: 400">Development versus production: Pick the right tool</span></h2>
<p><span style="font-weight: 400">AgentLens is designed for the </span><b>development loop</b><span style="font-weight: 400">, when you’re iterating on Agent Script, testing behavior in preview, and refining how your agent orchestrates. It helps you understand what happened in a test run, so you can make the next change with confidence.</span></p>
<p><span style="font-weight: 400">For </span><b>production observability</b><span style="font-weight: 400">, monitoring live agent conversations, tracking performance, and diagnosing issues in deployed agents, use</span><a href="https://help.salesforce.com/s/articleView?id=ai.generative_ai_platform_trace.htm&amp;type=5"> <span style="font-weight: 400">Agent Platform Tracing</span></a><span style="font-weight: 400">. That’s the built-in platform capability for tracing agent execution at scale in your org.</span></p>
<p><span style="font-weight: 400">A useful way to think about it:</span></p>
<ul>
<li style="font-weight: 400"><b>AgentLens</b><span style="font-weight: 400"> is the workbench microscope you use while building</span></li>
<li style="font-weight: 400"><b>Agent Platform Tracing</b><span style="font-weight: 400"> is the production dashboard you use after shipping</span></li>
</ul>
<h2><span style="font-weight: 400">Get started with AgentLens</span></h2>
<p><span style="font-weight: 400">AgentLens is open source and MIT licensed on</span><a href="https://github.com/msrivastav13/AgentLens"> <span style="font-weight: 400">GitHub</span></a><span style="font-weight: 400">. Try it on your own Agentforce agent traces, and if there’s a visualization that would help you debug faster, or a feature you’d like to see added,</span><a href="https://github.com/msrivastav13/AgentLens/issues"> <span style="font-weight: 400">open an issue</span></a><span style="font-weight: 400">.</span></p>
<p><span style="font-weight: 400">I built AgentLens because feedback loops matter. Whether you’re debugging Agentforce agents yourself or prompting a coding agent to do it for you, having a clear mental model changes how effectively you work. You write better prompts, catch orchestration issues faster, and gain a deeper understanding of how your agents actually behave.</span></p>
<h2><span style="font-weight: 400">Resources</span></h2>
<ul>
<li style="font-weight: 400"><a href="https://msrivastav13.github.io/AgentLens/"><span style="font-weight: 400">AgentLens web app</span></a></li>
<li style="font-weight: 400"><a href="https://marketplace.visualstudio.com/items?itemName=MohithShrivastava.agentlens-viewer"><span style="font-weight: 400">AgentLens VSCode extension</span></a></li>
<li style="font-weight: 400"><a href="https://github.com/msrivastav13/AgentLens"><span style="font-weight: 400">AgentLens open source repository</span></a></li>
<li style="font-weight: 400"><a href="https://github.com/trailheadapps/agent-script-recipes"><span style="font-weight: 400">Agent Script Recipes sample app</span></a></li>
</ul>
<h2><span style="font-weight: 400">About the author</span></h2>
<p><b>Mohith Shrivastava</b><span style="font-weight: 400"> is a Principal Developer Advocate at Salesforce with 15 years of experience building enterprise-scale products on the Agentforce 360 Platform. Mohith is currently among the lead contributors on Salesforce Stack Exchange, a developer forum where Salesforce Developers can ask questions and share knowledge. You can follow him on </span><a href="https://www.linkedin.com/in/mohith-shrivastava-9a36464a/"><span style="font-weight: 400">LinkedIn</span></a><span style="font-weight: 400">.</span></p>
<p>The post <a href="https://developer.salesforce.com/blogs/2026/05/agentlens-debug-agentforce-with-interactive-visualizations">AgentLens: Debug Agentforce with Interactive Visualizations</a> appeared first on <a href="https://developer.salesforce.com/blogs">Salesforce Developers Blog</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://developer.salesforce.com/blogs/2026/05/agentlens-debug-agentforce-with-interactive-visualizations/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<post-id xmlns="com-wordpress:feed-additions:1">206274</post-id><media:thumbnail url="https://d259t2jj6zp7qm.cloudfront.net/images/20260511140836/Thumbnail_Headshot-Screen-4-e1778533730382.png?w=1000" />
<media:content url="https://d259t2jj6zp7qm.cloudfront.net/images/20260511140836/Thumbnail_Headshot-Screen-4-e1778533730382.png?w=1000" medium="image" />
	</item>
		<item>
		<title>Intent-Driven Tool Selection Using Abilities in Agentforce Vibes</title>
		<link>https://developer.salesforce.com/blogs/2026/05/intent-driven-tool-selection-using-abilities-in-agentforce-vibes</link>
		<comments>https://developer.salesforce.com/blogs/2026/05/intent-driven-tool-selection-using-abilities-in-agentforce-vibes#respond</comments>
		<pubDate>Fri, 08 May 2026 08:07:20 +0000</pubDate>
		<dc:creator><![CDATA[Sarah Welker]]></dc:creator>
				<category><![CDATA[Agentforce]]></category>
		<category><![CDATA[Agentforce Vibes]]></category>
		<category><![CDATA[App Development]]></category>
		<category><![CDATA[Developer Tooling]]></category>
		<category><![CDATA[New Developments]]></category>
		<category><![CDATA[Apex]]></category>
		<category><![CDATA[app development]]></category>
		<category><![CDATA[developer tooling]]></category>

		<guid isPermaLink="false">https://developer.salesforce.com/blogs/?p=206255</guid>
		<description><![CDATA[<p>Use Abilities, the intelligent context activation system in Agentforce Vibes, to identify the most relevant Salesforce DX MCP Server tools for every request.</p>
<p>The post <a href="https://developer.salesforce.com/blogs/2026/05/intent-driven-tool-selection-using-abilities-in-agentforce-vibes">Intent-Driven Tool Selection Using Abilities in Agentforce Vibes</a> appeared first on <a href="https://developer.salesforce.com/blogs">Salesforce Developers Blog</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p><span style="font-weight: 400">For an AI coding agent to be truly effective, it must have access to the right tools at the right time. But with the sheer number of </span><a href="https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_mcp.htm"><span style="font-weight: 400">Salesforce DX MCP Server</span></a><span style="font-weight: 400"> tools available (and growing), it can be challenging for developers to manually select and configure the tools that their agents need. That’s where </span><a href="https://developer.salesforce.com/docs/platform/einstein-for-devs/guide/abilities.html"><span style="font-weight: 400">Abilities</span></a><span style="font-weight: 400">, a new feature in </span><a href="https://developer.salesforce.com/docs/platform/einstein-for-devs/overview"><span style="font-weight: 400">Agentforce Vibes</span></a><span style="font-weight: 400">, comes in. Abilities is an intelligent context activation system that helps Salesforce Developers automate their development environment. </span></p>
<p><span style="font-weight: 400">By leveraging RAG-based semantic retrieval, Abilities solves the growing tool selection problem by identifying the most relevant Salesforce DX MCP Server tools for every request. This approach keeps your execution environment focused while improving output quality and reducing token usage. </span></p>
<p><span style="font-weight: 400">In this post, we’ll examine the challenges of tool explosion, define how Abilities function, and dive into the mechanics of semantic retrieval and tool dependency expansion.</span></p>
<div style="width: 1670px;" class="wp-video"><video class="wp-video-shortcode" id="video-206255-1" width="1670" height="1080" preload="metadata" controls="controls"><source type="video/mp4" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260507124128/abilities.mp4?_=1" /><a href="https://d259t2jj6zp7qm.cloudfront.net/images/20260507124128/abilities.mp4">https://d259t2jj6zp7qm.cloudfront.net/images/20260507124128/abilities.mp4</a></video></div>
<h2><span style="font-weight: 400">The problem: Tool explosion and manual configuration</span></h2>
<p><span style="font-weight: 400">In Agentforce Vibes, context is everything. As the Salesforce Platform grows, the number of MCP (Model Context Protocol) servers grows with it, and today, there are more than 80 Salesforce DX MCP Server tools available from within Agentforce Vibes, including task-based tools that handle CLI commands, testing, code analysis, accessibility checks, DevOps operations, mobile, and more.</span></p>
<p><span style="font-weight: 400">Turning them all on at once creates problems: the prompt becomes larger, the model has too many choices, output quality drops, and token costs rise. But the opposite problem exists as well. If too few tools are available, Agentforce Vibes may not have the capabilities it needs to generate metadata, create Apex code, refactor LWCs, or successfully analyze code for security violations.</span></p>
<p>As the catalog of Salesforce DX MCP Server tools expands, several new challenges arise:</p>
<ul>
<li><b>Default limitations:</b> Given the sheer number of possible tools, we’ve only enabled a limited subset by default. This is due to concerns that activating too many tools might degrade the user experience or overwhelm the model.</li>
<li><b>User experience impact: </b>This often leads to sub-optimal code generation where the code may fail to compile, fail deployment, or ignore Salesforce development conventions.</li>
<li><b>Manual configuration barriers:</b> Developers can customize available tools, but doing so requires manual editing of the local <code>mcp_config.json</code> file and specific knowledge of internal MCP server tool names. Consequently, most developers never make these changes and rely entirely on the default toolset, even when additional tools would improve outcomes.</li>
</ul>
<p>
			  <span class="postimagessection_specify alignnone size-medium wp-image-206262" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260508102532/image2-e1778261163911.png?w=1000" class="postimages" width="1000" height="563" alt="Screenshot of the Agentforce Vibes configuration panel alongside a JSON settings file showing manual MCP server tool management." />
			  </span>
			</p>
<p><span style="font-weight: 400">We needed a way to give Agentforce Vibes exactly the tools it needs, exactly when it needs them.</span></p>
<h2><span style="font-weight: 400">The solution: Intelligent context activation with Abilities</span></h2>
<p><span style="font-weight: 400">Abilities are domain capabilities that define what Agentforce Vibes can do in a given development scenario. There is no manual configuration and no switching between development modes. The system responds directly to the developer’s intent. This keeps the execution environment small and focused while ensuring that Agentforce Vibes has the capabilities required to complete the development task.</span></p>
<p><span style="font-weight: 400">Examples include capabilities for:</span></p>
<ul>
<li style="font-weight: 400"><span style="font-weight: 400">Apex, LWC development</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">DevOps operations</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">Mobile development</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">Core platform administration</span></li>
</ul>
<p><span style="font-weight: 400">Each Ability bundles together the DX MCP Server tools associated with that capability.</span></p>
<p><span style="font-weight: 400">When a request arrives, Agentforce Vibes evaluates the developer’s prompt and determines which capabilities should be active for the task and exposes only the tools associated with those capabilities. This process is managed by an internal orchestration layer called the Ability Coordinator, which interprets the request and prepares the execution environment before the model is invoked. This happens automatically for every task and requires no configuration from the developer.</span></p>
<p><span style="font-weight: 400">Abilities are composable and a request may activate more than one capability. In practical terms, Abilities answer one question: What tools should Agentforce Vibes have access to right now?</span></p>
<h2><span style="font-weight: 400">How Skills and Abilities work together</span></h2>
<p><span style="font-weight: 400">Abilities and Skills serve different but complementary roles. Abilities handle context activation; they detect what you&#8217;re trying to do and automatically select the right Salesforce DX MCP tools for the task. This improves model focus and keeps output aligned with Salesforce best practices.</span></p>
<p><span style="font-weight: 400">Skills are reusable, task-level playbooks. They define how specific work gets done (e.g., refactoring a trigger, generating tests, running a deployment), so you don&#8217;t restate instructions every time.</span></p>
<p><span style="font-weight: 400">Abilities determine what tools are available. Skills define how the work gets done. Together, they let Vibes intelligently configure itself per task while keeping the developer in control.</span></p>
<h2><span style="font-weight: 400">What drives Abilities</span></h2>
<p><span style="font-weight: 400">Abilities use </span><a href="https://en.wikipedia.org/wiki/Retrieval-augmented_generation"><b>retrieval-augmented generation</b></a><b> (RAG)</b><span style="font-weight: 400"> to select tools. Instead of sending the full catalog of available tools to the model, Abilities retrieve the most relevant tools using semantic search. This allows the system to scale as the tool catalog grows while keeping prompts small.</span></p>
<h3><span style="font-weight: 400">How semantic retrieval works</span></h3>
<p><span style="font-weight: 400">To ensure that Agentforce Vibes selects the right tools without overwhelming the model, we use a RAG-based retrieval process. This happens in three phases: indexing the tools, matching them to your prompt, and then injecting the tools into the model’s execution context.</span></p>
<p>
			  <span class="postimagessection_specify alignnone size-medium wp-image-206263" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260508102533/image3-e1778261450531.png?w=1000" class="postimages" width="1000" height="259" alt="A flow diagram illustrating the three phases of RAG-based tool selection in Agentforce Vibes: Tool Embedding and Indexing, Prompt-to-Tool Matching, and Execution Context." />
			  </span>
			</p>
<h4><span style="font-weight: 400">Phase 1: Tool embedding and indexing</span></h4>
<p><span style="font-weight: 400">Before any user interaction occurs, we prepare the tool catalog for retrieval. The following process runs whenever the MCP tool catalog is updated:</span></p>
<ul>
<li style="font-weight: 400"><b>Vector conversion:</b><span style="font-weight: 400"> Each tool definition, including its name, description, parameters, and intended usage context, is normalized and converted into a vector embedding.</span></li>
<li style="font-weight: 400"><b>Storage:</b><span style="font-weight: 400"> These embeddings are stored in a vector database. This allows the system to identify tools based on their &#8220;meaning&#8221; and function rather than just matching keywords.</span></li>
</ul>
<h4><span style="font-weight: 400">Phase 2: Prompt-to-tool matching (retrieval)</span></h4>
<p><span style="font-weight: 400">When you submit a prompt, Agentforce Vibes performs a real-time similarity search:</span></p>
<ul>
<li style="font-weight: 400"><b>Prompt embedding:</b><span style="font-weight: 400"> Your prompt is converted into a vector embedding using the same model used for the tool definitions</span></li>
<li style="font-weight: 400"><b>Similarity search:</b><span style="font-weight: 400"> The system performs a cosine similarity search, comparing the prompt vector against the vector index of tools to find the best semantic matches</span></li>
<li style="font-weight: 400"><b>Top-K selection:</b><span style="font-weight: 400"> To balance performance and accuracy, the system ranks the results and selects the top matches, typically around ten tools</span></li>
</ul>
<h4><span style="font-weight: 400">Phase 3: Execution context</span></h4>
<p><span style="font-weight: 400">These selected tools are then injected into the model&#8217;s execution context as a temporary &#8220;function catalog.&#8221; This ensures the LLM has all the relevant capabilities it needs to fulfill your request while keeping the prompt size optimized for speed and cost.</span></p>
<h3><span style="font-weight: 400">Handling tool dependencies</span></h3>
<p><span style="font-weight: 400">Some MCP tools act as </span><b>orchestrators</b><span style="font-weight: 400"> that guide a workflow and require additional tools to complete the task. If only the orchestrator tool appears in the retrieved set, execution may fail because required tools are missing.</span></p>
<p><span style="font-weight: 400">Abilities address this with </span><b>post-selection expansion</b><span style="font-weight: 400">.</span></p>
<p>
			  <span class="postimagessection_specify alignnone size-medium wp-image-206261" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260508102529/image1_a5b01c-e1778261392433.png?w=1000" class="postimages" width="1000" height="299" alt="Flowchart showing the &quot;post-selection expansion&quot; process where an initial orchestrator tool triggers dependency checks to include required tools like deploy_metadata and run_apex_test in the final selection." />
			  </span>
			</p>
<p><span style="font-weight: 400">This ensures that the agent has the tools needed to complete the task while keeping the overall tool set small.</span></p>
<h2><b>Conclusion</b></h2>
<p><span style="font-weight: 400">From intent to execution, Abilities ensure that Agentforce Vibes has exactly what it needs, every time. By utilizing RAG-based semantic retrieval and automated dependency expansion, this system effectively manages the expanding catalog of Salesforce DX MCP tools to deliver high-quality, focused development environments without manual configuration.</span></p>
<p><span style="font-weight: 400">As Agentforce Vibes grows, the Abilities intelligent context activation system may expand to support:</span></p>
<ul>
<li style="font-weight: 400"><span style="font-weight: 400">Additional Salesforce and third-party MCP servers</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">Integration with Skills for task guidance once the right tools are activated</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">Richer tool metadata for retrieval</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">Improved dependency discovery</span></li>
</ul>
<h2><b>Resources</b></h2>
<ul>
<li style="font-weight: 400"><span style="font-weight: 400">Agenforce Vibes Developer Guide: </span><a href="https://developer.salesforce.com/docs/platform/einstein-for-devs/guide/abilities.html"><span style="font-weight: 400">Abilities</span></a></li>
<li style="font-weight: 400"><span style="font-weight: 400">Trailhead: </span><a href="https://trailhead.salesforce.com/content/learn/projects/quick-start-troubleshoot-code-with-dev-agent"><span style="font-weight: 400">Quick Start: Troubleshoot Code with Agentforce Vibes</span></a></li>
<li style="font-weight: 400"><span style="font-weight: 400">Trailhead: </span><a href="https://trailhead.salesforce.com/users/pozil/trailmixes/agentforce-vibes"><span style="font-weight: 400">Get Started with Agentforce Vibes</span></a></li>
<li style="font-weight: 400"><span style="font-weight: 400">Video: </span><a href="https://www.youtube.com/watch?v=HByDCHMFdsY&amp;list=PLgIMQe2PKPSIPk_YOY4XZn72y0yl-Zqt4"><span style="font-weight: 400">Agentforce Vibes Decoded</span></a></li>
</ul>
<h2><b>About the authors</b></h2>
<p><b>Jeff Douglas</b><span style="font-weight: 400"> is a Product Management Director at Salesforce working on Agentforce Vibes and AI-powered developer tools. A Salesforce Developer since 2007, and one of the original Salesforce MVPs, he helped launch Trailhead and build several of its core learning and assessment systems. Jeff is an Army veteran, former brewery owner, foster and adoptive parent, woodworker, and owner of a growing herd of mini Scottish Highland cows. Connect with him on </span><a href="https://www.linkedin.com/in/jeffdouglas/"><span style="font-weight: 400">LinkedIn</span></a><span style="font-weight: 400">.</span></p>
<p><b>Ken Lewis</b><span style="font-weight: 400"> is a Lead Member of Technical Services at Salesforce based in Oakland, CA. He formerly worked on Salesforce products for the Nonprofit sector, and enjoys making Salesforce products work best for all types of customers. Outside of work, you can find Ken playing racquetball, practicing on his home DJ setup, or exploring new restaurants and activities in the Bay Area. Connect with him on</span><a href="https://www.linkedin.com/in/kenslewis/"> <span style="font-weight: 400">LinkedIn</span></a><span style="font-weight: 400">.</span></p>
<p>The post <a href="https://developer.salesforce.com/blogs/2026/05/intent-driven-tool-selection-using-abilities-in-agentforce-vibes">Intent-Driven Tool Selection Using Abilities in Agentforce Vibes</a> appeared first on <a href="https://developer.salesforce.com/blogs">Salesforce Developers Blog</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://developer.salesforce.com/blogs/2026/05/intent-driven-tool-selection-using-abilities-in-agentforce-vibes/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<post-id xmlns="com-wordpress:feed-additions:1">206255</post-id><media:thumbnail url="https://d259t2jj6zp7qm.cloudfront.net/images/20260508080504/Generic-D-1-e1778252720313.png?w=1000" />
<media:content url="https://d259t2jj6zp7qm.cloudfront.net/images/20260508080504/Generic-D-1-e1778252720313.png?w=1000" medium="image" />
	</item>
		<item>
		<title>Agent Platform Tracing: Debug Agentforce with Trace Trees, SOQL, and Slack</title>
		<link>https://developer.salesforce.com/blogs/2026/05/agent-platform-tracing-debug-agentforce-with-trace-trees-soql-and-slack</link>
		<comments>https://developer.salesforce.com/blogs/2026/05/agent-platform-tracing-debug-agentforce-with-trace-trees-soql-and-slack#respond</comments>
		<pubDate>Thu, 07 May 2026 19:15:39 +0000</pubDate>
		<dc:creator><![CDATA[Trevor Scott]]></dc:creator>
				<category><![CDATA[Agentforce]]></category>
		<category><![CDATA[App Development]]></category>
		<category><![CDATA[Data Cloud]]></category>
		<category><![CDATA[Developer Tooling]]></category>
		<category><![CDATA[Data 360]]></category>
		<category><![CDATA[Platform Tracing]]></category>
		<category><![CDATA[Slack]]></category>
		<category><![CDATA[SOQL]]></category>

		<guid isPermaLink="false">https://developer.salesforce.com/blogs/?p=206243</guid>
		<description><![CDATA[<p>Trace Agentforce actions by capturing LLM calls, Flows, and Apex executions as queryable trees in Data 360. Learn to enable this service-level visibility and use Slackbot to pinpoint root causes instantly with natural language.</p>
<p>The post <a href="https://developer.salesforce.com/blogs/2026/05/agent-platform-tracing-debug-agentforce-with-trace-trees-soql-and-slack">Agent Platform Tracing: Debug Agentforce with Trace Trees, SOQL, and Slack</a> appeared first on <a href="https://developer.salesforce.com/blogs">Salesforce Developers Blog</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p><span style="font-weight: 400">Agent Platform Tracing captures every Agentforce action execution as an OpenTelemetry trace tree stored in Data 360, giving you a queryable record of every LLM call, flow execution, and Apex invocation in the chain. A single user utterance to an agent can trigger a cascade of downstream calls, and when you need to understand exactly what happened, a top-level error message rarely tells the full story. The actual issue (a slow LLM step, a misfired flow, an Apex class that never returned) is buried somewhere in the execution chain. Agent Platform Tracing surfaces that chain as a hierarchical tree showing what happened, how long each step took, and where the chain broke.</span></p>
<p><span style="font-weight: 400">The feature is based on the </span><a href="https://opentelemetry.io/docs/concepts/signals/traces/"><span style="font-weight: 400">OpenTelemetry standard</span></a><span style="font-weight: 400"> and stores all span data directly in Data 360, making it queryable alongside the rest of your org&#8217;s data with a single toggle flip.</span></p>
<h2><span style="font-weight: 400">How to enable Agent Platform Tracing</span></h2>
<p>
			  <span class="postimagessection_specify alignnone size-medium wp-image-206246" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260507110334/image1_4a3ce2-e1778177025756.png?w=1000" class="postimages" width="1000" height="282" alt="Screenshot showing Agent Platform Tracing enabled." />
			  </span>
			</p>
<p><span style="font-weight: 400">Enabling Agent Platform Tracing takes about two minutes:</span></p>
<ol>
<li style="font-weight: 400"><b>Toggle it on in Setup. </b><span style="font-weight: 400">Navigate to </span><b>Setup → Agent Platform Tracing</b><span style="font-weight: 400"> and flip the toggle to enabled. This starts writing span data to Data 360 for every Agentforce action execution in your org.</span></li>
<li style="font-weight: 400"><b>Verify Data 360 is provisioned.</b><span style="font-weight: 400"> Agent Platform Tracing stores spans in data model objects (DMOs), so your org needs Data 360 provisioned and active. If you&#8217;re already using Agentforce, this is likely already in place.</span></li>
<li style="font-weight: 400"><b>Check permissions. </b><span style="font-weight: 400">Users querying trace data need the Data Cloud Data Access permission set, plus read access to the </span><span style="font-weight: 400">ssot__TelemetryTraceSpan__dlm</span><span style="font-weight: 400"> and related DMOs.</span></li>
<li style="font-weight: 400"><b>Wait for data. </b><span style="font-weight: 400">Spans begin populating within minutes of the first Agentforce action execution after enablement. There&#8217;s no backfill of historical data.</span></li>
</ol>
<p><span style="font-weight: 400">Once enabled, trace data is queryable via SOQL against the Data 360 DMOs described in the sections below.</span></p>
<h2><span style="font-weight: 400">How Agent Platform Tracing builds a trace tree</span></h2>
<p><span style="font-weight: 400">The core concept of Agent Platform Tracing is straightforward: each instrumented service that is called when an Agentforce action executes generates a telemetry record called a </span><i><span style="font-weight: 400">span</span></i><span style="font-weight: 400">, and every span records its parent&#8217;s ID. That parent-child chain lets you reconstruct the execution sequence as a hierarchical tree, from the root interaction down through the instrumented downstream calls.</span></p>
<p><span style="font-weight: 400">Here&#8217;s what that looks like in practice. The following trace shows an agent action executing a flow that results in an error:</span></p>
<pre language="text">[OK] run.interaction (96afcfefaa6fbfe9) — 2,430ms
└── [OK] run.llmstep (9939b8bc33d12bfa) — 167ms
    └── [OK] run.topic.FlowAgentforce__FlowBuilderAutomationsTopic — 3ms
        └── [OK] run.llmstep (b3595456464fbe93) — 1,341ms
            └── [ERROR] run.action.Get_Account_179SB000000v31B — 481ms
                ├── [OK] run.invokeActions.FLOW — 274ms [InvocableAction]
                │   └── [OK] run.Get_Account.1 — 266ms [Flow]
                │       Attributes: flow.api.name=Get_Account, flow.api.version=1,
                │                   flow.execution.api.version=Spring '26,    
   |                    flow.type=AutolnchNoTrig
                │       └── [OK] run.createrecord.account — 42ms [Flow]
                │           Attributes: db.collection.name=Account, db.rows_affected=0,
                │                       db.operation.name=query
                └── [OK] run.llmstep (b4e5194e749ede24) — 884ms

</pre>
<p>A few key things to call out here: the <code>ssot__DurationNumber__c</code> field (e.g. 2,430ms) tells you how long each step took, and <code>ssot__StatusCode__c</code> (Status is always either <code>OK</code> or <code>ERROR</code>) tells you exactly where a chain broke.</p>
<p>Note that the flow ran successfully — <code>run.Get_Account.1</code> returned <code>OK</code> — but the parent action still errored. The reason is in the span attributes: <code>db.rows_affected=0</code> tells you the Account query returned nothing. Despite the operation being named <code>run.createrecord</code>, the <code>db.operation.name=query</code> attribute reveals it was actually performing a lookup, not a write, and that lookup came back empty. The action expected a result and didn&#8217;t get one. Execution continued anyway with a fallback <code>run.llmstep</code>, which is why the overall interaction didn&#8217;t terminate immediately.</p>
<p>Without the span attributes, you&#8217;d see a failed action and have no idea whether the flow ran, whether it touched the database, or what it found there.</p>
<h2>Comparing Agentforce session tracing and Agent Platform Tracing</h2>
<p>Agent Platform Tracing stores spans into Data Lake Object (DLOs) which get mapped into Data Model Object (DMOs) using the single source of truth (<code>ssot</code>) prefix. Before going further, it&#8217;s worth understanding how <a href="https://help.salesforce.com/s/articleView?id=ai.generative_ai_session_trace_about.htm&amp;language=en_US&amp;type=5"><u>Agentforce sSession Tracing</u></a> and Agent Platform Tracing differ.</p>
<table>
<tbody>
<tr>
<td><b>Feature</b></td>
<td><b>Level</b></td>
<td><b>Captures</b></td>
<td><b>Primary DMO</b></td>
<td><b>Join Field</b></td>
</tr>
<tr>
<td><span style="font-weight: 400">Session Tracing</span></td>
<td><span style="font-weight: 400">Planner</span></td>
<td><span style="font-weight: 400">Conversational flow: user input, subagent routing, agent response</span></td>
<td><span style="font-weight: 400">ssot__AiAgentInteraction__dlm</span></td>
<td><span style="font-weight: 400">ssot__TelemetryTraceId__c</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">Platform Tracing</span></td>
<td><span style="font-weight: 400">Service</span></td>
<td><span style="font-weight: 400">Back-end execution: LLM calls, Flow runs, Apex invocations, timing, errors</span></td>
<td><span style="font-weight: 400">ssot__TelemetryTraceSpan__dlm</span></td>
<td><span style="font-weight: 400">ssot__TelemetryTrace__c</span></td>
</tr>
</tbody>
</table>
<p>Agentforce Session Tracing — centered on <code>ssot__AiAgentInteraction__dlm</code> — is instrumented at the planner level and captures the <i>conversational</i> flow: what the user said, which subagent handled the request, and what the agent returned. Agent Platform Tracing, via <code>ssot__TelemetryTraceSpan__dlm</code>, is instrumented at the service level and captures the <i>back-end execution state</i> that powered that response. The span DMO is self-referential by design: <code>ssot__TelemetryParentSpanId__c</code> maps back to <code>ssot__Id__c</code>, enabling tree traversal from any node in either direction. Furthermore, because both DMOs share the exact same underlying Trace ID, you can join <code>ssot__TelemetryTraceId__c</code> directly to <code>ssot__TelemetryTrace__c</code>. This enables you to connect Agentforce session tracing to the specific back-end code execution provided by Agent Platform Tracing.</p>
<h2><span style="font-weight: 400">Querying trace data with SOQL</span></h2>
<p><span style="font-weight: 400">With SOQL, you can query these DMOs directly via the API to extract exactly the diagnostics you need. A good starting point is profiling performance by operation type, which quickly surfaces any parts of your agent execution that are consistently slow:</span></p>
<pre language="sql">SELECT ssot__OperationName__c,
       AVG(ssot__DurationNumber__c) AvgDuration,
       MAX(ssot__DurationNumber__c) MaxDuration,
       COUNT(Id) SpanCount
FROM ssot__TelemetryTraceSpan__dlm
WHERE ssot__StartDateTime__c &gt; 2026-01-01T00:00:00Z
GROUP BY ssot__OperationName__c
LIMIT 20
</pre>
<p><span style="font-weight: 400">Or we can query for all recent spans that have errors: </span></p>
<pre language="sql">SELECT ssot__Id__c, ssot__OperationName__c, ssot__TelemetryTrace__c,
       ssot__StartDateTime__c, ssot__DurationNumber__c, ssot__StatusCode__c
FROM ssot__TelemetryTraceSpan__dlm
WHERE ssot__StatusCode__c = 'ERROR'
ORDER BY ssot__StartDateTime__c DESC
LIMIT 20
</pre>
<p><span style="font-weight: 400">Or count errors across operation types:</span></p>
<pre language="sql">SELECT ssot__OperationName__c, COUNT(Id) SpanCount
FROM ssot__TelemetryTraceSpan__dlm
WHERE ssot__StatusCode__c = 'ERROR'
GROUP BY ssot__OperationName__c
LIMIT 20
</pre>
<p>Once we find a span we want to investigate, we can query for all related spans via <code>ssot__TelemetryTrace__c:</code></p>
<pre language="sql">SELECT ssot__Id__c, ssot__OperationName__c, ssot__TelemetryParentSpanId__c,
       ssot__ServiceName__c, ssot__StatusCode__c, ssot__DurationNumber__c,
       ssot__StartDateTime__c, ssot__EndDateTime__c,
       ssot__TelemetrySpanAttributeText__c
FROM ssot__TelemetryTraceSpan__dlm
WHERE ssot__TelemetryTrace__c = 'YOUR_TRACE_ID'
ORDER BY ssot__StartDateTime__c ASC
</pre>
<p>We can then reconstruct the tree client-side by matching each span&#8217;s <code>ssot__TelemetryParentSpanId__c</code> to another span&#8217;s <code>ssot__Id__c</code>, treating <code>null</code> or <code>0000000000000000</code> as the root.</p>
<h2><span style="font-weight: 400">Query Agent Platform Tracing data from Slack with Slackbot</span></h2>
<p><span style="font-weight: 400">Because this data lives in Data 360, you can easily query the data to observe Agentforce. One effective pattern is wiring instructions into a Slack canvas, feeding it to Slackbot, and using it as the natural language interface for our trace data. This makes it easy for anyone to digest the trace information, as long as Slackbot is set up to query the information correctly. Whether you&#8217;re responding to a user complaint or proactively checking for errors, the workflow is the same: ask the bot, get the trace tree, pinpoint the issue, and discuss a fix, without ever leaving Slack. No log spelunking, no guesswork. Just a conversation with Slackbot to find the root cause and come up with a potential solution.</span></p>
<p><span style="font-weight: 400">The approach I take when providing instructions to Slackbot is simple: I provide the schemas, sample queries, join patterns, and main use cases. You can find some of the instructions I use in my  </span><a href="https://github.com/trevorscott/AgentPlatformTracingSlackbotInstructions"><span style="font-weight: 400">Agent Platform Tracing Slackbot Instructions GitHub repo</span></a><span style="font-weight: 400">. </span></p>
<p><span style="font-weight: 400">You’ll need to make sure that your Slack is connected to an org that has Agent Platform Tracing enabled. Once you do, just add the instructions for Slackbot into a canvas and either add the canvas as a tab for Slackbot or paste it into the chat at the beginning of your conversation.</span></p>
<p><span style="font-weight: 400">Here&#8217;s a typical Slackbot exchange:</span></p>
<pre language="text">You:  Why did interaction b9e8f7b4 take 4 seconds?

Slackbot:  I queried all spans for trace b9e8f7b4. The interaction
           took 2,690ms total. Here's the breakdown:

           run.interaction           2,690ms  OK
           └─ run.llmstep              139ms  OK
              └─ run.topic               3ms  OK
                 └─ run.llmstep        838ms  OK
                    └─ run.action      327ms  OK
                       └─ run.llmstep 1,011ms  OK   ← slowest span

           The bottleneck is the final run.llmstep span (1,011ms),
           which accounts for 38% of total duration.
</pre>
<p><span style="font-weight: 400">Once you have Slackbot set up with Agent Platform Tracing, you can ask things like:</span></p>
<ul>
<li style="font-weight: 400"><span style="font-weight: 400">Why did this agent interaction take 4 seconds?</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">Which subagent is responsible for the most errors this week?</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">What are the most common errors for a given operation type? </span></li>
<li style="font-weight: 400"><span style="font-weight: 400">What’s the root cause of this issue that a user is asking about? </span></li>
</ul>
<h2><span style="font-weight: 400">Joining Agentforce Session Tracing and Agent Platform Tracing data</span></h2>
<p><span style="font-weight: 400">With the right instructions, Slackbot can query and join both Agentforce Session Tracing and Agent Platform Tracing data together. Joining them provides a full trace tree for end-to-end observability of Agentforce. With both features, we have complete visibility of agent activity and issues in a couple of minutes.</span></p>
<p><span style="font-weight: 400">Use this when you want to correlate a user&#8217;s conversational context (Agentforce Session Tracing) with the back-end execution details (Agent Platform Tracing). This is an optional advanced use case; both features work independently.</span></p>
<h3><span style="font-weight: 400">How the join works</span></h3>
<p><span>Because </span><code>ssot__TelemetryTraceId__c</code><span> on </span><code>ssot__AiAgentInteraction__dlm</code><span> matches </span><code>ssot__TelemetryTrace__c</code><span> on </span><code>ssot__TelemetryTraceSpan__dlm</code><span>, they can be used for a direct join. This means you can fetch all spans for an interaction in a single query.</span></p>
<h3><span style="font-weight: 400">Full joined hierarchy</span></h3>
<pre language="text">Session (ssot__AiAgentSession__dlm)
└── Interaction (ssot__AiAgentInteraction__dlm)
    └── Step (ssot__AiAgentInteractionStep__dlm)
        └── Span (ssot__TelemetryTraceSpan__dlm)
            └── Span (ssot__TelemetryTraceSpan__dlm)
                └── ...
</pre>
<h3><span style="font-weight: 400">Query pattern: Get all spans for a known interaction</span></h3>
<pre language="sql">SELECT ssot__Id__c, ssot__OperationName__c, ssot__TelemetryParentSpanId__c,
       ssot__StartDateTime__c, ssot__DurationNumber__c, ssot__StatusCode__c
FROM ssot__TelemetryTraceSpan__dlm
WHERE ssot__TelemetryTrace__c = 'TELEMETRY_TRACE_ID_FROM_INTERACTION'
ORDER BY ssot__StartDateTime__c ASC
</pre>
<h2><span style="font-weight: 400">Getting started</span></h2>
<p><span style="font-weight: 400">Generative AI adds complexity to modern stacks that traditional logging wasn&#8217;t designed to observe, and the cost of those blind spots compounds the longer they take to find. Agent Platform Tracing removes the blind spots. And, when you combine it with Slackbot, it is far easier to observe, troubleshoot, and fix Agentforce issues in production so your agents can get back to work without issues. Check out the </span><a href="https://github.com/trevorscott/AgentPlatformTracingSlackbotInstructions"><span style="font-weight: 400">Agent Platform Tracing Slackbot Instructions GitHub repo</span></a><span style="font-weight: 400"> for working Slackbot instructions that you can copy-and-paste into a canvas to get started, and the</span><a href="https://help.salesforce.com/s/articleView?id=ai.generative_ai_platform_trace.htm&amp;type=5"><span style="font-weight: 400"> Agent Platform Tracing documentation</span></a><span style="font-weight: 400"> for setup instructions and the full data model reference.</span></p>
<p><b>Trevor Scott</b><span style="font-weight: 400"> is a Senior Manager of Product Management at Salesforce, focused on enabling customers with security and telemetry data to help developers and admins ship more confidently.</span></p>
<p>The post <a href="https://developer.salesforce.com/blogs/2026/05/agent-platform-tracing-debug-agentforce-with-trace-trees-soql-and-slack">Agent Platform Tracing: Debug Agentforce with Trace Trees, SOQL, and Slack</a> appeared first on <a href="https://developer.salesforce.com/blogs">Salesforce Developers Blog</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://developer.salesforce.com/blogs/2026/05/agent-platform-tracing-debug-agentforce-with-trace-trees-soql-and-slack/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<post-id xmlns="com-wordpress:feed-additions:1">206243</post-id><media:thumbnail url="https://d259t2jj6zp7qm.cloudfront.net/images/20260507105210/Generic-C-1-e1778176344923.png?w=1000" />
<media:content url="https://d259t2jj6zp7qm.cloudfront.net/images/20260507105210/Generic-C-1-e1778176344923.png?w=1000" medium="image" />
	</item>
		<item>
		<title>Introducing the Data 360 MCP Server (Developer Preview)</title>
		<link>https://developer.salesforce.com/blogs/2026/05/introducing-the-data-360-mcp-server-developer-preview</link>
		<comments>https://developer.salesforce.com/blogs/2026/05/introducing-the-data-360-mcp-server-developer-preview#respond</comments>
		<pubDate>Wed, 06 May 2026 15:15:49 +0000</pubDate>
		<dc:creator><![CDATA[Alba Rivas]]></dc:creator>
				<category><![CDATA[Announcements]]></category>
		<category><![CDATA[App Development]]></category>
		<category><![CDATA[Data Cloud]]></category>
		<category><![CDATA[Salesforce Releases]]></category>
		<category><![CDATA[Data 360]]></category>
		<category><![CDATA[Developer Preview]]></category>
		<category><![CDATA[MCP Server]]></category>
		<category><![CDATA[Model context protocol]]></category>

		<guid isPermaLink="false">https://developer.salesforce.com/blogs/?p=206226</guid>
		<description><![CDATA[<p>Explore the new open-source MCP Server in Developer Preview. Learn how to connect AI assistants like Cursor and Claude Code directly to your Data 360 APIs via a standard stdio transport.</p>
<p>The post <a href="https://developer.salesforce.com/blogs/2026/05/introducing-the-data-360-mcp-server-developer-preview">Introducing the Data 360 MCP Server (Developer Preview)</a> appeared first on <a href="https://developer.salesforce.com/blogs">Salesforce Developers Blog</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p><span style="font-weight: 400">The</span><a href="https://modelcontextprotocol.io/"> <span style="font-weight: 400">Model Context Protocol (MCP)</span></a><span style="font-weight: 400"> is changing how we expose APIs to AI agents. To continue our headless journey, Salesforce just released the</span><a href="https://github.com/forcedotcom/d360-mcp-server"> <span style="font-weight: 400">Data 360 MCP server</span></a><span style="font-weight: 400"> as an open-source GitHub repository in Developer Preview. This new server connects the Salesforce Data 360 APIs to any</span><span style="font-weight: 400"> MCP client that supports stdio transport, such as Claude Code, Cursor, or Codex</span><span style="font-weight: 400">. </span></p>
<p><span style="font-weight: 400">This post covers how the new MCP server works, how to install it locally, and how your feedback will help us shape the future of the tool.</span></p>
<h2><b>Solving the context window challenge</b></h2>
<p><span style="font-weight: 400">Data 360 has a massive API surface. Exposing every endpoint directly as a tool quickly overwhelms a large language model&#8217;s (LLM) context window. To solve this, our engineering team implemented a novel approach </span><a href="https://blog.cloudflare.com/enterprise-mcp/"><span style="font-weight: 400">inspired by Cloudflare&#8217;s research on MCP server tool management at scale</span></a><span style="font-weight: 400">. Instead of registering the approximately 200 REST API operations individually, this MCP server consolidates them behind three facade tools:</span></p>
<ul>
<li><code><span>search</span></code><span>: Discovers tools by intent, keyword, or family.</span></li>
<li><code><span>payload_examples</span></code><span>: Fetches working JSON payloads so the LLM understands how to structure complex requests.</span></li>
<li><code>execute</code><span>: Runs the specific underlying tool by name and passes the correct parameters.</span></li>
</ul>
<p><span style="font-weight: 400">When an LLM wants to perform a task, it uses a typical workflow: it </span><b>searches</b><span style="font-weight: 400"> for the right capability, fetches a </span><b>payload example</b><span style="font-weight: 400"> to understand the required data structure, and then </span><b>executes </b><span style="font-weight: 400">the operation. This approach saves context window space and improves the accuracy of the AI&#8217;s actions while remaining flexible enough to support the ever-growing headless capabilities of Data 360 far into the future.</span></p>
<p>
			  <span class="postimagessection_specify alignnone size-medium wp-image-206231" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260506074656/image1-e1778078834420.png?w=1000" class="postimages" width="1000" height="594" alt="Sequence diagram illustrating the three-step MCP facade workflow: the AI assistant first calls search to discover the segment tool, then calls payload_examples to retrieve the JSON template, and finally calls execute to send the payload to the Salesforce Data 360 API." />
			  </span>
			</p>
<h2><b>What the Data 360 MCP server includes</b></h2>
<p><span style="font-weight: 400">Under the hood, the three facade tools give your AI client access to hundreds of REST API operations organized into tool families. These tools connect directly to most of the general availability (GA) APIs on Data 360.</span></p>
<table>
<tbody>
<tr>
<td><b>Tool Family</b></td>
<td><b>Description</b></td>
</tr>
<tr>
<td><span style="font-weight: 400">DLO / DMO</span></td>
<td><span style="font-weight: 400">Manage raw data tables (Data Lake Objects) and your unified schema (Data Model Objects)</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">Data Streams</span></td>
<td><span style="font-weight: 400">Ingest data from generic sources, Salesforce CRM, Snowflake, or Amazon S3</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">Mappings</span></td>
<td><span style="font-weight: 400">Map source fields to target Data Model Object fields</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">Data Transforms</span></td>
<td><span style="font-weight: 400">Build, run, validate, and schedule SQL-based transformations</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">Identity Resolution</span></td>
<td><span style="font-weight: 400">Define rules that unify customer profiles, then publish and run them</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">Calculated Insights</span></td>
<td><span style="font-weight: 400">Author SQL-defined metrics; enable, disable, run, validate, and query them</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">Segment / Dataspace</span></td>
<td><span style="font-weight: 400">Build and publish audience segments; manage dataspaces and their members</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">Connection</span></td>
<td><span style="font-weight: 400">Discover connectors and create, update, or test connections to data sources</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">Query</span></td>
<td><span style="font-weight: 400">Run SQL queries; query profiles, calculated insights, and data graphs; explore metadata</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">Activation / Data Action</span></td>
<td><span style="font-weight: 400">Send segments to external platforms and trigger automated data actions</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">Semantic Data Models</span></td>
<td><span style="font-weight: 400">Build semantic models for business intelligence — data objects, dimensions, measures, calculated fields, metrics, and relationships</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">AI and Search</span></td>
<td><span style="font-weight: 400">Configure Retrieval-Augmented Generation (RAG) retrievers and vector or hybrid search indexes for AI workloads</span></td>
</tr>
<tr>
<td><span style="font-weight: 400">Other</span></td>
<td><span style="font-weight: 400">Deploy data kit bundles, publish real-time events, handle GDPR requests, use AI-assisted mapping helpers, and apply preset mappings</span></td>
</tr>
</tbody>
</table>
<h2><b>Getting started: installation and authentication</b></h2>
<p><span style="font-weight: 400">During this Developer Preview, the MCP server is designed for local execution and is not yet multitenant. This means each running instance connects a single user to a single Salesforce org.</span></p>
<p><span style="font-weight: 400">To run the server, you need Java 17 or later, Maven 3.9 or later, and a Salesforce org with Data 360 enabled. You can use an </span><a href="https://www.salesforce.com/products/free-trial/developer"><span style="font-weight: 400">Agentforce Developer Edition org</span></a><span style="font-weight: 400"> or a </span><a href="https://trailhead.salesforce.com/content/learn/modules/data-cloud-in-flows/set-up-a-custom-data-cloud-playground"><span style="font-weight: 400">Data 360-enabled Trailhead playground</span></a><span style="font-weight: 400"> if you want to test it in an isolated environment. The server communicates via </span><span style="font-weight: 400">stdio</span><span style="font-weight: 400">, so it will work with any MCP client that supports this transport layer. Once your org is ready, follow the instructions in the </span><a href="https://github.com/forcedotcom/d360-mcp-server"><span style="font-weight: 400">README</span></a><span style="font-weight: 400"> to connect your agent and start building.</span></p>
<p><span style="font-weight: 400">The GitHub repo contains an installer script that helps set up dependencies and configure common MCP clients for use with the server. </span></p>
<p>
			  <span class="postimagessection_specify alignnone size-medium wp-image-206238" >
			    <img loading="lazy" decoding="async" src="https://d259t2jj6zp7qm.cloudfront.net/images/20260506081157/image2_F.gif?w=800" class="postimages" width="800" height="480" alt="Animation showing a terminal session in which the Data 360 MCP server is installed and configured for use with Claude Code." />
			  </span>
			</p>
<h2><b>Help us shape the general availability release</b></h2>
<p><span style="font-weight: 400">The new Data 360 MCP Server enables you to connect powerful LLMs to your Salesforce data without hitting context window limits. By using a novel facade tool architecture, we&#8217;ve made roughly 200 API operations easily accessible for agents and coding assistants. </span></p>
<p><span style="font-weight: 400">The Developer Preview is a critical step before we integrate this architecture directly into the Salesforce platform for general availability. By releasing it as open-source now, we aim to speed up platform integration and gather direct feedback from developers. Install the server today, test it with your local tools, and share your </span><a href="https://github.com/forcedotcom/d360-mcp-server/issues"><span style="font-weight: 400">feedback on GitHub</span></a><span style="font-weight: 400"> to help us prepare for the GA release. </span></p>
<p><span style="font-weight: 400">When the Data 360 MCP server becomes generally available, we&#8217;ll offer it as a </span><span style="font-weight: 400">Salesforce Hosted MCP Server</span> <a href="https://developer.salesforce.com/docs/platform/hosted-mcp-servers/guide/servers-reference.html"><span style="font-weight: 400">alongside other product integration MCP servers</span></a><span style="font-weight: 400">. In the meantime, our entire Data 360 team will be testing it internally alongside you to build and refine a collection of Data 360 agent skills; stay tuned for more news on those!</span></p>
<h2><b>About the authors</b></h2>
<p><b>Alba Rivas</b><span style="font-weight: 400"> works as a Principal Developer Advocate at Salesforce. You can follow her on</span> <a href="https://www.linkedin.com/in/alba-rivas/"><span style="font-weight: 400">Linkedin</span></a><span style="font-weight: 400">.</span></p>
<p><a href="https://www.linkedin.com/in/cpeterson"><b>Chris Peterson</b></a><span style="font-weight: 400"> is a Senior Director of Product Management at Salesforce, currently working on Data 360 Headless. </span></p>
<p>The post <a href="https://developer.salesforce.com/blogs/2026/05/introducing-the-data-360-mcp-server-developer-preview">Introducing the Data 360 MCP Server (Developer Preview)</a> appeared first on <a href="https://developer.salesforce.com/blogs">Salesforce Developers Blog</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://developer.salesforce.com/blogs/2026/05/introducing-the-data-360-mcp-server-developer-preview/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<post-id xmlns="com-wordpress:feed-additions:1">206226</post-id><media:thumbnail url="https://d259t2jj6zp7qm.cloudfront.net/images/20260506080754/DoubleHeadshot-2-e1778080091980.png?w=1000" />
<media:content url="https://d259t2jj6zp7qm.cloudfront.net/images/20260506080754/DoubleHeadshot-2-e1778080091980.png?w=1000" medium="image" />
	</item>
		<item>
		<title>GraphQL Mutations Now Available in LWC: Create, Update, and Delete Records</title>
		<link>https://developer.salesforce.com/blogs/2026/05/graphql-mutations-now-available-in-lwc-create-update-and-delete-records</link>
		<comments>https://developer.salesforce.com/blogs/2026/05/graphql-mutations-now-available-in-lwc-create-update-and-delete-records#respond</comments>
		<pubDate>Tue, 05 May 2026 15:00:28 +0000</pubDate>
		<dc:creator><![CDATA[Ben Sklar]]></dc:creator>
				<category><![CDATA[Announcements]]></category>
		<category><![CDATA[App Development]]></category>
		<category><![CDATA[Developer Tooling]]></category>
		<category><![CDATA[Lightning Web Components]]></category>
		<category><![CDATA[announcement]]></category>
		<category><![CDATA[GraphQL]]></category>
		<category><![CDATA[GraphQL Mutations]]></category>
		<category><![CDATA[lwc]]></category>
		<category><![CDATA[platform]]></category>

		<guid isPermaLink="false">https://developer.salesforce.com/blogs/?p=206215</guid>
		<description><![CDATA[<p>Create, update, and delete Salesforce records directly in LWC with GraphQL mutations. Streamline your data transactions and handle bulk changes without the need for custom Apex.</p>
<p>The post <a href="https://developer.salesforce.com/blogs/2026/05/graphql-mutations-now-available-in-lwc-create-update-and-delete-records">GraphQL Mutations Now Available in LWC: Create, Update, and Delete Records</a> appeared first on <a href="https://developer.salesforce.com/blogs">Salesforce Developers Blog</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p><span style="font-weight: 400">Salesforce Developers, we have an exciting update that extends the data management story for Lightning Web Components (LWC): </span><b>GraphQL mutations are here!</b></p>
<p><span style="font-weight: 400">We introduced the newest version of the GraphQL wire adapter (</span><a href="https://developer.salesforce.com/docs/platform/lwc/guide/reference-graphql.html"><span style="font-weight: 400">lightning/graphql</span></a><span style="font-weight: 400">) in Spring ‘26. Now we’re introducing support for using GraphQL beyond just querying in LWC, adding the ability to easily </span><b>create, update, and delete </b><span style="font-weight: 400">records via the GraphQL Mutations API.</span></p>
<h2>Executing GraphQL mutations in LWC with <code>executeMutation</code></h2>
<p>In LWC, interacting with the Salesforce GraphQL API for mutations is achieved via the <code>executeMutation</code> function from the <code>lightning/graphql </code><code>module.</code><br />
The <code>executeMutation</code> function allows you to execute one or more data changes. The function accepts an object parameter with the same three properties as the GraphQL wire: <code>query</code>, <code>variables</code>, and <code>operationName</code>. For example, to update an Account’s name:</p>
<pre language="javascript">import { gql, executeMutation } from 'lightning/graphql';

const updateRecord = gql(`
            mutation UpdateAccount($input: AccountUpdateInput!) {
                uiapi {
                    AccountUpdate(input: $input) {
                        success
                    }
                }
            }
`);

 await executeMutation({
            query: updateRecord,
            variables: {
                input: {
                    Id: '001xx000003GYiCAAW',
                    Account: {
                        Name: 'Acme[Updated]',
                    },
                },
            },
        });
</pre>
<p>The<span> </span><code>executeMutation</code> function supports dynamic query creation, just like the updated GraphQL support provided by <code>lightning/graphql</code>, so you can build these mutation inputs dynamically with JavaScript.</p>
<h2><span style="font-weight: 400">Data consistency considerations</span></h2>
<p><span style="font-weight: 400">Lightning Data Service keeps Salesforce record data consistent across UIAPI and GraphQL. With GraphQL mutations, this mostly works seamlessly, but we do have a few tips for getting the best results: </span></p>
<ul>
<li style="font-weight: 400"><span style="font-weight: 400">Newly created records will not appear in existing GraphQL query results until the query is refreshed, depending on its filter criteria and cache state. This applies to create and update mutations that affect records included in a query result set. </span></li>
<li style="font-weight: 400"><span style="font-weight: 400">Updated record fields may be propagated to subscribed Lightning Data Service wire adapters when their cached data overlaps. It may not be necessary to refresh in all scenarios.</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">Deleted records will properly be removed from Lightning Data Service wire results. Refreshes are not required for delete operations.</span></li>
</ul>
<h2><span style="font-weight: 400">See it in action: The LWC recipes showcase</span></h2>
<p><span style="font-weight: 400">To help you get started immediately, we have added dedicated examples to the </span><a href="https://github.com/trailheadapps/lwc-recipes/tree/main/force-app/main/default/lwc"><span style="font-weight: 400">LWC Recipes GitHub repository</span></a><span style="font-weight: 400">.</span></p>
<p>The new <b><code>graphqlMutation</code></b> components demonstrate how to use <code>executeMutation</code> to handle create, update, and delete operations through GraphQL. By exploring the source code for the <code>graphqlMutation</code> components, you can see practical implementations of data mutation, success handling, and error display via toast events.</p>
<p><span style="font-weight: 400">You can clone the LWC Recipes repository to your local machine and deploy the app to your Salesforce org to test this new functionality.</span></p>
<p><span style="font-weight: 400">GraphQL Mutations fully unlock bulk updates and tree saves for Lightning Web Components (LWC) without custom Apex. You can now not only view your Salesforce data efficiently but also modify it seamlessly, bringing richer, data-driven applications to life. This capability significantly streamlines the development of complex UIs that require simultaneous creation, update, or deletion of multiple related records. The integration of GraphQL Mutations marks a major step toward empowering LWC developers with a more modern and powerful way to manage data transactions on the Salesforce platform.</span></p>
<h2><span style="font-weight: 400">Developer Resources</span></h2>
<p><span style="font-weight: 400">Ready to start mutating your data? Here are the resources you need to dive in:</span></p>
<ul>
<li style="font-weight: 400"><b>Developer Documentation: </b><a href="https://developer.salesforce.com/docs/platform/lwc/guide/reference-graphql-wire.html"><b>lightning/graphql</b></a></li>
<li style="font-weight: 400"><b>GitHub repository: </b><a href="https://github.com/trailheadapps/lwc-recipes/tree/main/force-app/main/default/lwc"><b><u>LWC Recipes</u></b></a> – Find the new <code>graphqlMutation</code> components and other examples.</li>
<li style="font-weight: 400"><b>API Developer Guide: </b><a href="https://developer.salesforce.com/docs/platform/graphql/guide/mutations-schema.html"><b>GraphQL API</b></a><span style="font-weight: 400"> – Details on the mutation schema and structure.</span></li>
<li style="font-weight: 400"><b>Postman Collection: </b><a href="https://www.postman.com/salesforce-developers/salesforce-developers/folder/dgk52e4/mutation?sideView=agentMode"><b>Salesforce Platform APIs/GraphQL</b></a><span style="font-weight: 400"> – Helpful for testing mutation structure.</span></li>
<li style="font-weight: 400"><b>Best Practices Guide: </b><a href="https://developer.salesforce.com/docs/platform/graphql/guide/graphql-wire-lwc-best.html"><b>GraphQL Wire Adapter Best Practices</b></a><span style="font-weight: 400"> – Maximize your GraphQL potential.</span></li>
</ul>
<h2><span style="font-weight: 400">About the Authors</span></h2>
<p><b>Stephen Carraway</b><span style="font-weight: 400"> is a Lead Member of Technical Staff at Salesforce from the Lightning Data Service team. When he’s not building client data libraries, he&#8217;s busy woodworking, gardening, and 3D printing. </span></p>
<p><b>Ben Sklar</b><span style="font-weight: 400"> is a Director of Product Management at Salesforce responsible for UI API, the Salesforce GraphQL API, the Lightning Data Service, and AI Developer Kit. Ben is a major fan of GraphQL, but when not using GraphQL, you can find him playing ultimate frisbee or skiing during the winter. Follow him on </span><a href="https://www.linkedin.com/in/benjamin-sklar/"><span style="font-weight: 400">LinkedIn</span></a><span style="font-weight: 400">.</span></p>
<p>The post <a href="https://developer.salesforce.com/blogs/2026/05/graphql-mutations-now-available-in-lwc-create-update-and-delete-records">GraphQL Mutations Now Available in LWC: Create, Update, and Delete Records</a> appeared first on <a href="https://developer.salesforce.com/blogs">Salesforce Developers Blog</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://developer.salesforce.com/blogs/2026/05/graphql-mutations-now-available-in-lwc-create-update-and-delete-records/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<post-id xmlns="com-wordpress:feed-additions:1">206215</post-id><media:thumbnail url="https://d259t2jj6zp7qm.cloudfront.net/images/20260504111148/Generic-A-e1777918325209.png?w=1000" />
<media:content url="https://d259t2jj6zp7qm.cloudfront.net/images/20260504111148/Generic-A-e1777918325209.png?w=1000" medium="image" />
	</item>
	</channel>
</rss>
