Showing posts with label agentforce. Show all posts
Showing posts with label agentforce. Show all posts

Monday, 13 October 2025

Structured Output from Flow Agent Actions in Winter '26

Image created by ChatGPT 5o based on a prompt by Bob Buzzard


Introduction

When preparing for the Credera Winter '26 release webinar, the release notes for this feature gave me significant pause for thought. Not because it was an awesome change that I'd been waiting ages for, nor that it was something out of left field that I couldn't wait to try. Instead it was because I didn't understand how it worked. The release notes talked about custom agent actions returning specific fields, so did that mean it was the action itself that returned complex data types? There was only one way to find out.

Giving it a Go

Once I'd waited for my Agentforce developer edition to be upgraded to Winter '26 I was able to try out this new functionality. In order to understand how much effort I had to put in around my actions, I started off putting in zero effort. Masterful inactivity has always served me well!

The first thing I tried was a simple screen flow, with the first element an AI Agent Action, as this was the key to defining structured output. 


First crack out of the box and I have a winner! Without even having to create a custom action, Copilot for Salesforce is available as an AI Agent Action. Clicking into this showed that the new Structured Output functionality was available with this action.


After a few false starts (the AI Agent Action wouldn't accept collections of records etc) I had a simple flow that would take in an account Id, retrieve the opportunities associated with the account, convert them to a simple JSON structure and ask the AI Agent to calculate the total amount of the opportunities. For my AI Agent Action, I give a relatively simple prompt grounded with the opportunity information.

and for my structured output, I specified a single field - the total amount.


Executing this in debug mode gave me the answer to my first question - did that mean it was the action itself that returned complex data types? No, in this case I'm simply sending a request to an LLM and it will give a text response. The Salesforce platform handles the conversion to structured output.



And I can then use that structured output like I would any other complex object, in this case in a screen displaying the total.


Note that the "container" for the structured output is actually a Dynamic Apex Class that you can access through setup:


Conclusion


To answer my earlier question:

Did that mean it was the action itself that returned complex data types? 

It did indeed - there was no need for me to create anything outside of the action for the results to be stored in, I just defined the field and used natural language to explain what should be stored in there. The platform created an Apex class to store the information and populated it from the LLM output.

This is pretty cool - it allows low code to convert the unstructured output from an LLM into structured output for use in downstream processing. Prior to this feature an Apex developer would likely have been needed to help, but now it can all be handled by a low coder.

Of course this is a terrible example. If I really wanted the total, why wouldn't I calculate it while iterating the records, rather than pulling together a bunch of text and then incurring the expense and time overhead of an LLM callout - Agents Augment Automation, they don't replace it. 

I chose this example as it was easy to put together to prove the concept. In the real world I'd only use LLMs to handle tasks that regular automation couldn't, like figuring out the customer sentiment from a bunch of activities associated with the Opportunities. More work to set that up though, and harder to explain.

More Information



Tuesday, 7 October 2025

Agentforce Vibes - First Look, Data Model

  Image created by ChatGPT 5 based on a prompt from Bob Buzzard 


Introduction

We all knew this was coming, right? Salesforce has long considered itself the cool kid in enterprise technology, so they were always going to jump on the vibe coding bandwagon. After reading the Salesforce Developers blog post on Agentforce Vibes I was keen to give it a go. 

I took the approach that I wanted the Agent to be truly autonomous, so my plan was to agree with everything it wanted to do, and then once everything was deployed to my org, I'd try it out and review everything at that point. This is how I'd work with a human junior assisting me, although I'd obviously be available to talk through their ideas if they wanted, which agents typically don't need.

Setup

Setup was as easy as it gets. I'm using VS Code and simply by switching to the Agent Dev view we were off and vibing.


I spun up a scratch org, activated the MCP server for the Salesforce CLI, and then tried to figure out what to do with it.

What to Vibe Out

I didn't just want to vibe some straightforward additional Apex to an existing code repository, as I'm sure that's one of the smoke tests of this new functionality. If it can't do that, it's going to be a tough time on the socials for Salesforce. The part of application development I've always wanted to speed up, especially for my side projects, is creating the data model and permission sets. Doing this directly through XML metadata is quite error-prone, and doing it through Setup takes a while. As a coder, this is typically a task I just want out of the way so I can start cutting some Apex. 

I decided to give it the kind of task that I was intimately familiar with, as I'd given it to many graduates back in my BrightGen days. The concept is an onboarding application, with a bunch of templated journeys broken down into steps that can be instantiated and assigned to a new joiner, with a specified start date and manager etc. There's a bunch of requirements around calculating completion dates and current state that require roll up summaries and formula fields, so it's a good introduction to data modelling for those new to Salesforce.

I created a prompt of around 130 words that covered the key concepts in natural language. I avoided giving any clues, so rather than talking about roll up summaries and master details, I used phrases like "this is calculated from the max values in the steps for the journey". Probably quite close to the real instructions that I gave humans.

I gave the agent the prompt and asked it to generate a plan, which it did. 

The plan was frankly excellent.

It had picked up all the nuance of the requirements - identified where Master-Detail relationships were required, understood that templates were separate to the actual journeys and needed to be modelled as their own objects, and came up with recommendations around security and deployment. It also suggested a bunch of extra fields, permission sets, and a flow to create journeys from templates. Most of this was later tasks for the grads so I told it to skip those. I then signed off on the plan and sat back to watch the agent at work.

Creating the Metadata

One thing I found a little tedious was the agent wanted me to okay every file before creating it, even though I'd ticked the box for auto-approve. I didn't check any further into this, so it's possible there's another setting I needed to look at. I typically don't review people's work piecemeal as they create individual components, so I just okayed them all straight away. What I saw as they were being generated looked plausible, and after about 10 minutes it had completed all the work. So I asked to to deploy its work to my scratch org.

Deploying the Files (or where it all went awry)

The initial attempt at deployment threw up an error that you can't specify both the apexTests and apexTestLevel parameters. Slightly unexpected, but it was easily able to move on. 

The next attempt threw up a few errors:

  • The agent had used <picklist> instead of <valueSet> which wasn't compatible with the metadata API version I'd specified. Slightly unexpected again, as I'd been asked which API version I wanted to generate the metadata for, but again something easily fixed.
  • It had set a Private sharing model for an object on the detail side of a Master-Detail relationship. It turns out this was for the sharing model and the external sharing model, which caused problems in later attempts as it changed one but not the other.
  • The roll up summary metadata fields weren't correct, so the agent suggested changing them. It turned out that the suggested new fields were no more valid (<summaryTable>).
As the agent was in charge, I okayed all of its suggested changes and it tried again. We then entered a doom cycle of attempting to deploy, getting errors, and highly variable suggestions for fixes. 

I think that the agent wanted to apply fixes for every error in a one go, which isn't always the best approach with deployments, as one error can cascade into a lot of failures. My approach is to fix errors one at a time and retry the deployment, so that I have a handle on what I've changed and what difference it made. The agent would want to change the metadata to fix every error at once, even when the underlying error was a custom object failing to deploy. 

My favourite was where a parent object in a relationship couldn't deploy because the roll up summary metadata was wrong, which threw an error on the child object. The agent felt that this was an issue with the child object and the case was the relationship being Master-Detail. It changed the relationship  to a Lookup field, but sadly it left the roll up summary metadata in place, thus finding more errors at the next deployment.

After a couple of attempts the agent had used up all my requests and switched me to the core model. I wondered if this might be better, given that it's a Salesforce hosted (and presumably trained) model, but sadly that wasn't the case. If I was paying for requests to be burned by something that wasn't even following documented metadata standards, I'd likely be a little miffed.

Eventually the agent proudly announced that it had completed the deployment, even though I could see the request had failed.



Creating and Deploying Permission Sets (or the Folie à Deux) 


Checking the org also confirmed nothing had been deployed, but this is vibe coding where the facts don't matter and the agents are in charge, so I feigned ignorance and asked it to now create some permission sets for me - an admin and a manager, obviously giving quite a lot of detail.

Again, the plan here was excellent - it understood my prompt, picked out the nuance and generated plausible files. The agent had clearly been emboldened by how easily I was tricked into believing the deployment was successful, and jumped straight to it. This time I decided I couldn't continue to enable its flights of fancy and called it out. It folded like a cheap suit. 



This was comfortingly familiar - often ChatGPT and others give me completely incorrect code and when called out on it, fess up immediately. It didn't offer to fix it again though, just told me it was sorry, the system was broken, and what needs fixing. Vibe Confessions.

At this point I took over and fixed the errors - <writable> instead of <editable> for a custom field in the permission set was the most egregious, in case you were wondering. 

But Seriously Folks!


It's easy to mock Agentforce Vibes (I mean, just look at what it was doing - this stuff writes itself!), but the issues I've identified will be easily fixed. It reminds me of the first release of Agentforce for Developers - the test class code generated by that was fairly awful, but it wasn't long before it was quite reliable. If we didn't have Dreamforce '25 starting in a week, I'm pretty sure we wouldn't be seeing this yet. I guess that data model metadata might also not be its strong suit, but it's GA and it understood the ask, so I think it's fair enough to call out the performance.

So for this, admittedly slightly complex, data modelling task, Agentforce Vibes is top tier for planning, but decidedly middling for execution. You'll need to be experienced with Salesforce metadata to guide it through generating the correct metadata, or fixing it yourself. In terms of generating a list of tasks to carry out in the UI, it was pretty amazing, it just wasn't great at handling those tasks itself in metadata. 

While the above probably reads as somewhat negative (and yes, snarky!), that isn't really the case. Using Agentforce Vibes was way faster than trying to create this all myself.  Either via XML or through the UI. I probably had it all in my scratch org with appropriate permission sets in around 60-90 minutes. The caveat here is that if I didn't have my many years of experience working with metadata, I doubt I'd have got it deployed at all. 

Once the execution catches up with the planning, which I'm sure won't be that long, it will be a different story and a really helpful sidekick.

This is only my first look - I'll be back to this scenario to vibe code some flow, lightning component and asynchronous Apex and I'll keep you updated on how I got on.

Related Information



Tuesday, 5 August 2025

Agentforce Custom Lightning Types

Introduction

The Summer '25 release of Salesforce (or maybe prior, given Agentforce releases are on a monthly cycle) introduced Custom Lightning Types, which finally gives us a degree of fine-grained control over the user interface. At the time of writing (August 2025) this is only for actions that use Apex classes for requests and responses.

In essence, a Custom Lightning Type configures an Agentforce user interface override for an Apex class. The Apex class can either be used as the input to send information to an Agentforce action, or as the output containing the response to the user request. 

Example

I've been playing around with a Custom Lighting Type to display overview information from my Limit Tracker that I created for my session at London's Calling 2025. For this I wanted two custom types:

  • An input that captured the number of days of Limit Snapshots to include in the overview
  • An output that showed the Heap and CPU details from the snapshots
I also wanted these to be more interesting than a simple form field to capture an integer and a list of values, but that only comes into play when developing the Lightning Web Components to handle the user interface, so I'll come to those later.

Output

My custom Apex action returns the following class:

public class LimitConsumption { 
    @InvocableVariable
    public String name;
                
    @InvocableVariable
    public List<LimitSnapshot> snapshots;         
        
    public LimitConsumption(String name, List<LimitSnapshot> snapshots) {
        this.name = name;
        this.snapshots = snapshots;
    }
}

It can sometimes be tricky to pinpoint the exact class returned from an action, as they tend to be inner classes and nested inside response wrappers. An easy way to find out exactly which class Agentforce will use is to go through the New Action process and see what it picks up for the output:


If you aren't from a developer background, the class reference might look a bit odd, but it breaks down as:

  • c__ this is the namespace the class is present in. c__ means the default (or lack of) namespace. 
  • LimitConsumptionOverview is the outer, or containing class
  • The $ separator indicates this is an inner class of LimitConsumptionOverview
  • LimitConsumption is the name of the actual inner class 
Once I know which class my type with will be working with, I can create an entry in the lightningTypes source folder, in this case limitConsumptionResponse, to make it clear this is used to render the response from an Agent.
   
The schema.json file configures the type to work with my custom class:
{
  "title": "Limit Consumption",
  "description": "Overview of limit consumption by a particular piece of Apex code",
  "lightning:type": "@apexClassType/c__LimitConsumptionOverview$LimitConsumption"
}

The lightning:type entry is the key piece of wiring that couples this Custom Lightning Type with my Apex class.

Next I had to decide how I wanted to render this information. Something that couldn't easily be found on the regular detail pages was appealing, and as it is handled by a Lightning Web Component I have access to the full power of JavaScript and the Lightning Design System. I decided to return a tabbed interface containing a chart :



and a list of values:



Note that I've taken a leaf out of the Salesforce examples and my custom Apex action returns the same list of fake data regardless of how it's invoked.

You can find the Lightning Web Component at : limitConsumption - it uses the Chart.js library to create the bar chart.

Once my Lightning Web Component is in place, I need to create a file in my Custom Lightning Type folder named lightningDesktopGenAi named renderer.json:

  {
    "collection": {
      "renderer": {
        "componentOverrides": {
          "$": {
            "definition": "c/limitConsumption"
          }
        }
      }
    }
  }

The key aspect here is the componentOverrides which defines my Lightning Web Component (limitConsumption in the default namespace) as the override to render the type. 

Input

My custom Apex action relies on the following input class:

public with sharing class SliderIntegerWrapper {
    @InvocableVariable
    public Integer value;
}

Note that this is simply wrapping an Integer value - while lots of the examples I've seen are around complex classes containing multiple values/nested classes, they don't have to. In this case I just want a funkier way to enter the value, so I need an Apex class to hold it.

To capture the information I decided to go with a slider component - note that this did give Agentforce a little trouble with the rendering - once the value got to double figures it wrapped to the next line!


Similar to the output, I create a lightningType folder named sliderInteger and define the schema.json to couple the type to my class:

{
  "title": "Slider Integer",
  "description": "Slider Integer",
  "lightning:type": "@apexClassType/c__SliderIntegerWrapper"
}

as this time my class is top level, the entry just contains c__ (for the default namespace) and the name of the class.

The Lightning Web Component that provides the input slider can be found at sliderInteger. 

This time, once my Lightning Web Component is in place, I need to define a lightningDesktopGenAi/editor.json file to define it as the override:

{
  "editor": {
    "componentOverrides": {
      "$": {
        "definition": "c/sliderInteger"
      }
    }
  }
}

The Agent Action

Now that I have my Custom Lightning Types defined and the overrides configured, I can create the Agentforce action that makes use of them, based on my LimitConsumptionOverview invocable Apex class. When defining the inputs I choose my SliderInteger type for the daysWrapper :


and for outputting the limit consumption information, I choose the LimitConsumptionResponse type:


Executing this action brings both my types into play, as can be seen from the following short video:




Lessons Learned

Something I'd strongly recommend when working with Custom Lightning Types is to build yourself a simple test page so that you can try them out without having to go via Agentforce every time you make a change. While it doesn't sound onerous, making requests and supplying inputs gets tedious very quickly! I created a test harness Lightning Web Component (limitConsumptionHarness) that sends fake data to the output component and handles the event from the input component, and it's saved me a lot of time.

The first scratch org I tried this in, I'd already used the example from the Salesforce docs, and for some reason only that one would be picked up. After spending a couple of hours trying various things, and creating yet another set of custom types, I spun up a new scratch org and it all worked fine. No idea what went wrong, but by the same token I was learning and tweaking so it could have been anything.

Make sure to use distinct names for your types, classes and Lightning Web Components. My first attempt I used the same name for the type and the component and quickly lost track of what I was configuring where.

More Information








Saturday, 22 March 2025

Keep Your Agentforce Dev Org Alive and Kicking


Image generated by OpenAI GPT4o in response to a prompt by Bob Buzzard

This post was updated on 12th April to point the Github repo links to V1.0, as a pull request to allow multiple dev orgs to be "renewed" at once was merged to the main branch. Thanks Warren Walters for the PR.

Introduction

One of the major announcements at TrailblazerDX '25 was the availability of Salesforce Developer Editions with Agentforce and Data Cloud. This is something that just about everyone has been asking for since the first generative AI features went GA in April 2024. Everything else that wasn't associated with a paid contract expired - Trailhead specials after 5 days and Partner SDOs couldn't be taken past 90 days, and even getting that far required raising a case to extend it past the default 30 days. The icing on the cake was the metadata support wasn't fantastic, which meant manually recreating features after spinning up a new org, which gets a bit samey after the fifth time.

Developer Editions don't live forever though - if you don't use them you lose them. After 180 days for the non-Agentforce variant (now known as legacy) and an evanescent 45 days if you want the generative AI features. Although to be fair, the signup page states that Salesforce "may" terminate orgs that are unused for 45 days rather than "will", but if you've put a lot of effort in you don't want to take any risks.

45 days sounds like a long time and it's easy to assume you'll manage to remember a login every 6 weeks or so, but my experience is that it's easy to get distracted and miss a slot. Machines are much better at remembering to do things on a schedule, so this is one task that I prefer to hand off - in this case to a Github Action.

Access Dev Org Action

Github Actions allows automation of software workflows through YAML (YAML Ain't Markup Language) files. Typically I'd use actions for continuous integration tasks on a project - automated build and test every night, for example - but I can also use it for something simpler. In this case, running a Salesforce CLI command against my dev org. If you set up your environment and secret name as I have, you'll be able to use my YAML file exactly as is.

Setup Dev Org

The first thing to do is get your new dev org and setup CLI access. Sign up for a new Agentforce dev org at : 

https://www.salesforce.com/form/developer-signup/?d=pb

Then connect it to the Salesforce CLI using the command:

> sf org login web -o AFDevOrg

Login with your username/password and approve the oauth access.

Execute the following CLI command:

> sf org display -o AFDevOrg --json --verbose

and copy the Sfdx Auth Url output value

Now you have this value, you can move on to the Github steps.

Create Your Repository

In order to use Github actions on a free account, your repository will need to be public. This doesn't mean that your Dev Org becomes public property, as you'll be storing the Sfdx Auth Url in an environment secret that only you as the repository owner can see:



Create Your Environment and Secret

Once you've created your repository, you need an environment to store your secret - click the Settings tab on the top right and choose the Environments option on the left hand menu:

Click the New environment on the resulting page, then name your environment and click the Configure environment button:


On the resulting page, scroll down to the Environment secrets section and click the Add environment secret button:

Name your secret, paste the Sfdx Auth Url value in the Value textbox and click the Add secret button.


Create and Execute Your Action

The final setup step is to create the YAML file for your action. This needs to live in the .github/workflows repository subfolder and can be called anything you like - I've gone for:

.github/workflows/renew.yaml

Once the file is present, clicking on the Actions tab will show the name of the action in the All workflows list on the left hand side - Renew Agentforce Dev Org Lease in this case.


Click on the name to see the run history and other options. There are no runs yet, but I've defined a workflow_dispatch event trigger so that I can run it on demand - in my experience this is well worth adding.


Start a run by clicking the Run workflow dropdown and the resulting Run workflow button:

I find that either the page doesn't refresh or I can't wait for that to happen, so I click the Actions tab again to see the In progress run:


Clicking on the run name gives me a little more detail:


And clicking the card shows me workflow steps - I've waited until they all completed successfully, so my run is green!


Switching out to my dev org, upon checking my user record I can see that there's an entry matching the action execution, although obviously it comes from a Github IP address in the US:


And that's it. As well as the workflow_dispatch event trigger, I've also specified a cron trigger so that it executes at 20:30 every Monday - more than every 45 days, but that gives me some wiggle room if my job starts failing and I don't get around to fixing it quickly.

More Information





Saturday, 26 October 2024

Einstein Copilot vs Complex Queries

Image created by GPT-4o based in a prompt by Bob Buzzard

Introduction

Now that Agentforce (for Service at least) is GA we have access to the latest Atlas Reasoning Engine. That's the theory at least - I haven't seen a way to find out what version is in use, which models it has access to etc, but that doesn't worry me too much as I can't change or influence it anyway. Anecdotally I do feel that the ability to handle requests with more than one step has improved over the last few months, but this sounded like a step change - Chain of Thought reasoning and an iterative approach to finding the best response! 

My focus continues to be on Copilot (aka Agentforce for CRM, or whatever name it's going by this week), but I'm writing rather more custom actions than I'd like. Each of these introduces a maintenance overhead and as Robert Galanakis wisely wrote "The code easiest to maintain is the code that was never written", so if there's a chance to switch to standard functionality I'm all over it.

The Tests

Where I've found standard Copilot actions less than satisfactory in the past is around requests that require following a relationship between two objects and applying filters to each object. Show me my accounts created in the last 200 days with contacts that I've got open tasks against, that kind of thing. Typically it would satisfy the account ask correctly but miss the contact requirement. Now I can easily create an Apex action to handle this request, but the idea of an AI assistant is that it handles requests for me, rather than sending me the requirements so I can build a solution!

I've created 4 products with similar names:

  • Cordless Drill 6Ah
  • Cordless Drill 4Ah
  • Cordless Drill 2Ah
  • Travel Cordless Drill
and created a single Opportunity for the Cordless Drill 8Ah. I then ask some questions about this.

Test #1


Ask Copilot to retrieve Opportunities based on the generic product name 'Cordless Drill'

When I've tested this in the past, Copilot has refined 'Cordless Drill' to one of the four available products and then search for Opportunities containing that product. Sometimes it gets lucky and picks the right one, but more often than not it picks the wrong one (3 -1 odds) and tells me I don't have any.

The latest Copilot gets this right first time.



and checking the Query Records output shows the steps involved:



  • First it looked for products matching 'Cordless Drill'
    A limit of 10,000 seems a bit large, but I guess this isn't being passed on to an LLM and consuming tokens.
  • Then it finds the opportunities which have line items matching any of the 'Cordless Drill' products.
  • Then it pulls the information about the Opportunity.
    Interesting that it only narrows it to my Opportunities at this point - it feels like the line item query could get a lot of false positives.
So I can pick the odd hole, but all in all a good effort.

Test #2


The next test was to add some filtering to the opportunity aspect of the request - I'm only interested in opportunities that are open. Once again, Copilot has no problem handling this request:


Test #3


The final test was using a prompt that had failed in earlier tests. This introduced a time component - the opportunities had to be open and created in the last 300 days, and used slightly different working, asking for opportunities that include "the cordless drill product".

This time Copilot was wrong-footed:


My assumption here was that the date component had tripped it up - maybe it didn't include today - or the "the cordless drill product" had resulted in the wrong product being chosen. Inspecting the queries showed something else though:


  • The products matching 'cordless drill' had been identified correctly
    This was through a separate query, presumably because I'd mentioned 'product'
  • The opportunity line items are queried for the products, but this time the query is retrieving the line item Id rather than the related Opportunity Id
  • An attempt is then made to query opportunity records that are open, created in the last 300 days and whose Id matches the line item Id, which will clearly never be successful. 
Rewording the request to "Show my open opportunities for the last 300 days that include cordless drills" gave me the correct results, so it appears use of the keyword 'product' changed the approach and caused it to lose track of what it was supposed to be doing.

Conclusion


The latest reasoning engine is definitely an improvement on previous versions, but it still gets tripped up with requests that reference multiple sObject types with specific criteria. 

While rewording the request did give a successful response, that isn't something I can see going down well with users - they just want to ask what is on their mind rather than figure out how to frame the request so that Copilot will answer it.

So I can't retire my custom actions just yet, but to be fair to Salesforce they have said that not all aspects of the Atlas Reasoning Engine will be available until February 2025. That said, I'm not sure I'd be happy if I'd been charged $2 to see it get confused!

Related Posts




Saturday, 5 October 2024

Agentforce - The End of Salesforce Human Capital?

Image generated by GPT-4o based on a prompt by Bob Buzzard

It's been a couple of weeks since Dreamforce and according to Salesforce there were 10,000 Agents built by the end of the conference, which means there's probably more than 20,000 now. One of those is mine, which I built to earn the Trailhead badge while waiting for the start of a Data Cloud theatre session and it did only take a few minutes.

So does this mean we need to sit back and prepare a the life of leisure while the Agents cater to our every whim?

The End of Humans + Salesforce?

Is this the end of human's working on/in Salesforce? Well not for some time in my opinion - these are very entry level tasks right now, and highly reliant on existing automation to do the actual work of retrieving or changing data. I suppose it's possible that eventually we'll end up with a perfect set of Agent actions (and supporting flows/Apex), but given we haven't achieved anything like that kind of reusability in the automation work that we've carried out over the last 20 odd years in Salesforce, it seems hopeful that we'll suddenly crack it. Even with the assistance of unlimited Agents. Any reports of our demise will be greatly exaggerated.

Fewer Humans + Salesforce?

This seems more plausible - not because of the current Agent capabilities displacing humans, but the licensing approach that Salesforce are taking. By moving away from per-seat licensing to per-conversation, Salesforce are clearly signalling that they expect to sell fewer licenses once Agentforce is available. 

Again, I don't think we're anywhere close to this happening, but it's the direction of travel. What it probably will do is given organisations pause for thought when creating their hiring plans next year. Will quite so many entry level recruits be required compared to previous years? 

Without Juniors, Where are the Seniors?

Something that often seems to be glossed over when talking about how generative AI will replace great swathes of the workforce is succession planning. Everyone who is now working as a Senior <anything> started out as a Junior <anything>, learned a bunch of stuff, gained experience and progressed. Today's Seniors won't last forever, there's a few years certainly, but eventually they'll run out of steam. And if there are no Juniors being hired, where do our crop of Seniors come from by 2034 and beyond?

It's likely to be one of two ways:

  • We grow them differently. Using AI we can fast-track their experience and reduce the amount they have to learn and retain themselves. Rather than people organically encountering teachable moments in customer interactions, we'll engineer those scenarios using an "<insert role here> Coach". The coach will present as a specific type of customer in a specific scenario, receive assistance and then critique the performance.
  • We don't need them, as the AI is so incredibly powerful that it exceeds the sum of all human knowledge and experience and can perform any job at any level.
I'm expecting the first way, but if I'm wrong I'm ready to welcome our Agent overlords.

Conclusion

No, I don't think Agentforce means the end of Human Capital in the Salesforce ecosystem. It does mean we need to do things differently though, and we shouldn't get so excited about the technology that we forget about the people. 

Related Posts