Custom scoped tools
Developer
Custom tools are purpose-named invocable actions scoped to one domain. The generic actions cover everything; a scoped tool covers one thing, so an agent can pick a tool by its purpose. A tool called Sales Desk Context, with a purpose statement, tells the agent which records it answers over. Generate them on Deploy → Custom.
How it works
@InvocableMethod(label='Sales Desk Context' category='ContextWorks'
description='Everything a seller needs about an account and its open business. Pass any covered record Id; uncovered objects return the current coverage list.')
public static List<Response> execute(List<Request> requests) {
// ...
ctxl.EntityRequest req = new ctxl.EntityRequest();
req.domainApiName = 'sales_desk';
req.toolName = 'SalesDeskGetRecordsAction';
req.recordId = request.recordId;
req.level = 'detailed';
req.format = 'markdown';
response.result = ctxl.Entity.load(req);
// ...
}
- The class names a domain, not an entity list. It reads the domain record at call time, so adding an object to the domain widens what the tool covers with no code change.
toolNamestamps telemetry. It becomes the Surface value in Usage, so this tool’s loads read on their own.- The description states a purpose, so it stays true when the domain’s contents change.
The code is yours to edit. Sharpen the @InvocableMethod description, add inputs, post-process the payload. Keep toolName, or Usage stops attributing the loads, and keep domainApiName, or the tool stops following the domain.
Generate the classes
Deploy → Custom
| Setting | What it does |
|---|---|
| Domain | Which domain’s roster the tools read through |
| Level | Pin a level, or expose it as a caller input |
| Format | Pin markdown, JSON, or both (the JSON payload with the markdown rendering inside it) — or expose it as an input |
You get six classes, each with a Copy button:
| Class | Role |
|---|---|
<Domain>GetCatalogAction | Discovery — what this domain serves right now |
<Domain>FindRecordsAction | Filtered sets from the domain |
<Domain>GetRecordsAction | One record in depth, entity chosen by the domain |
<Domain>GetBriefsAction | The standing frame the domain serves — injected briefs first, in order |
<Domain>GetSkillAction | A procedure the domain carries, fetched by name |
<Domain>UpdateRecordsAction | Updates the domain permits, with its confirmation posture |
The write tool is where pinning the domain matters most. The domain decides whether it permits writes at all, which fields an agent may change, and whether a person confirms first. An agent handed the pinned class cannot reach past any of it. → Write access
Pin level or format when the tool has one job. Fewer inputs is less for an agent to get wrong. Expose them when the same tool serves several depths; the generated class adds the input with an agent-readable description.
Deploy the classes
The classes live in your org and namespace. Deploy them as you deploy any Apex. They call only the package’s public API, Entity, EntityRequest and EntityFindRequest, so package upgrades and changes to what a domain carries don’t break them.
Register them
Setup → Agent Actions → New → Apex, once per class, or add them as MCP tools on a server. Name each action exactly as the class — the same rule as the built-in actions. Step 3A on the Deploy page shows the agent action table; 3B covers MCP.
To add them to an existing agent, put the domain’s actions in a topic of their own, then add a transition from your agent’s router. One topic per domain keeps the agent’s choices clear. Starting fresh? The Agentforce page generates a whole agent. Swap its apex:// targets for your class names.
Leave the update tool out of the topic if that agent should not write. The domain still has to allow the write, but a tool the agent never sees is the clearer statement.
Error handling
Pass a record whose object the domain doesn’t serve and the tool returns a structured answer naming what the domain does cover, rather than throwing, so the agent can re-plan. The catalog tool gives the same answer up front. Agents should call it first.
Custom source or custom tool?
| You want | Build |
|---|---|
| A new kind of context — computed, external, scored | An enrichment |
| A new way to address existing context | A scoped tool |