A client’s contact-centre team deployed an Agentforce service agent to handle “where’s my order” and “update my details” conversations. It worked, mostly. Then it started telling customers their refund had been processed when it hadn’t, and nobody could say why. The agent didn’t crash. It didn’t throw an error. It just answered confidently, and wrong.
That’s the thing nobody warns you about when you move from Apex to Agentforce. A failed trigger gives you a stack trace. A wrong agent answer gives you nothing. The reasoning that produced it happened somewhere between a topic classifier, a set of instructions, and an action call, and none of those fail loudly. You have to go looking.
Start with the transcript, not the model
Before you touch instructions or actions, pull the actual conversation trace. In Agent Builder, the Testing and Activity tab shows you which topic got selected for a given utterance, which instructions were active, which action fired, and what came back from it. This is the single most useful screen in the whole build, and most teams don’t open it until something’s already gone wrong in production.
Reproduce the exact utterance that caused the bad answer, not a paraphrase of it. Wording matters more than you’d expect. “Has my refund gone through” and “did you process my refund” can route to different topics if your topic descriptions and sample utterances aren’t tight, and a different topic means different instructions and different actions available. Before you assume the model reasoned badly, check whether it was even looking at the right topic.
Topic misclassification is the usual suspect
Most wrong answers trace back to the agent picking the wrong topic before it ever starts reasoning about the actual request. I’ve seen “Order Status” and “Return Request” topics both include sample utterances about “where is my order”, because both teams writing them figured it was relevant to their topic too. The classifier has to pick one, and when the boundary is fuzzy, it guesses. Once it’s in the wrong topic, every instruction and action downstream is wrong for the question actually being asked, and the agent has no way of knowing that.
Fix the overlap directly. Write topic descriptions that describe what’s unique about that topic, not what’s generally true about customer service. Add sample utterances that cover the awkward phrasing customers actually use, not just the clean ones from your requirements doc. And test with utterances deliberately chosen to sit near the boundary between two topics. If you only test the easy cases, you’ll ship a classifier that’s never been asked a hard question.
Watch for instructions stacking on top of each other
Global instructions, topic-level instructions, and action-level guidance all apply at once, and they don’t fail loudly when they contradict each other. A global instruction telling the agent to “always confirm identity before discussing account details” combined with a topic instruction that says “answer order status questions directly” can produce an agent that sometimes skips verification, depending on which instruction the model weights more heavily for that phrasing. You won’t see an error. You’ll see inconsistent behaviour that looks random until you lay every active instruction for that topic side by side.
Action inputs are where reasoning meets reality
An action’s description isn’t documentation for your team. It’s the thing the model reads to decide whether to call that action and what to pass it. If the description of an input parameter is vague, generic, or copied from a different action, the agent will fill it with its best guess rather than asking the customer to clarify. That’s how you get an action called with the wrong Case Id, or a flow invoked with a date range that doesn’t match what the customer actually asked for.
Go back through your action and input descriptions the same way you’d review a public API contract. Say exactly what the field is, what format it expects, and when it should be left blank versus when the agent should ask a clarifying question first. If an action can return an error state, make sure that error gets surfaced back to the agent in a way it can act on, not swallowed into a generic failure message that gets smoothed over into a confident-sounding non-answer.
Grounding gaps don’t look like gaps
When an agent is grounded on knowledge articles or Data Cloud records and the grounding doesn’t return anything useful, a well-tuned language model doesn’t say “I don’t know.” It produces the most plausible answer it can construct from general pattern, and that answer often sounds exactly as confident as a correctly grounded one. This is the failure mode that worries me most in production, because it’s invisible from the outside. The customer gets a fluent, specific-sounding answer that happens to be fabricated.
Check what grounding actually returned for the conversation in question, not what you assume it should have returned. If the retrieval came back empty or low-relevance, that’s your answer right there, and the fix is either better source coverage or an explicit instruction telling the agent what to do when grounding comes up empty: ask a clarifying question, hand off to a human, anything other than guessing.
Build the regression set before you ship the fix
Once you’ve found the actual cause, whatever you change, rerunning the one failing utterance isn’t enough to call it fixed. Build a small set of utterances that cover the topic boundary you just tightened, the instruction conflict you just resolved, or the action input you just clarified, including a few phrasings you haven’t tried yet. Agentforce’s testing centre lets you run these as a set rather than one at a time, which matters because fixing one misclassification often shifts behaviour on utterances that were working fine before.
This is the part teams skip under deadline pressure, and it’s exactly the part that catches the fix that solves today’s bug while quietly breaking three others. A service agent giving customers wrong information about their own refund isn’t a UX rough edge. It’s the kind of thing that erodes trust in the channel fast, and it’s worth the extra hour of testing before it goes back out.