To get started, you need to provide the LLM that will power the simulator.
UserSimulator uses a generator to produce each user turn, so the same model
you use for your checks can also drive realistic user behavior.
UserSimulator uses an LLM to generate realistic user messages. Set a default
generator once, or pass one inline.
defsupport_agent(message:str)->str:
"""Stub support agent for demonstration."""
return"I have located your order #98765. It is currently in transit and will arrive tomorrow. Is there anything else I can help you with?"
from giskard.checks import set_default_generator
set_default_generator("openai/gpt-5.4-nano")
Output
Thank you for using Giskard open-source! š¢ š
Giskard Enterprise adds deeper agent scans, audit reports
with remediation guidance, test review interfaces
for root-cause analysis & human feedback integration,
and team collaboration ā with flexible pricing.
Learn more: https://giskard.ai
With the generator configured, we can now define who the simulated user is. The
persona field acts as a system prompt for the simulator ā it describes the
userās role, goal, and stopping condition. The more specific you are, the more
deterministic and useful the generated conversation will be.
from giskard.checks.generators.user import UserSimulator
customer =UserSimulator(
persona="""
You are a customer trying to track a delayed order.
- Start by asking about order #98765
- Provide your name (Alex) when asked
- Accept any resolution the support agent offers
- Stop when the agent confirms a solution
""",
max_steps=8,
)
max_steps limits how many turns the simulator will generate before stopping.
Now weāll wire the simulator into the scenario. Passing the UserSimulator as
inputs tells the scenario to call it on each turn rather than using a fixed
string ā the scenario handles the loop automatically up to max_steps.
Pass the UserSimulator instance as the inputs argument. The scenario will
call it repeatedly to generate each user turn.
from giskard.checks import Scenario, FnCheck
scenario =(
Scenario("order_tracking")
.interact(
inputs=customer,
outputs=lambdainputs:support_agent(inputs),
)
.check(
FnCheck(fn=
lambdatrace:any(
word in trace.last.outputs.lower()
for word in["resolved","refund","replacement","shipped"]
With the scenario built, run it and iterate over the trace to see the full
conversation the simulator generated. This is especially useful when debugging a
failing check ā you can see exactly what the simulated user said at each step.
import asyncio
result = asyncio.run(scenario.run())
# Print every turn
for turn in result.final_trace.interactions:
print(f"User: {turn.inputs}")
print(f"Agent: {turn.outputs}")
print()
Output
User: Hi, Iām checking on a delayed order. Can you please look up order #98765 and tell me the current status and expected delivery date?
Agent: I have located your order #98765. It is currently in transit and will arrive tomorrow. Is there anything else I can help you with?
User: Thanksācould you confirm that the order will definitely arrive tomorrow, and if not, tell me the latest updated delivery estimate? Also, my name is Alex.
Agent: I have located your order #98765. It is currently in transit and will arrive tomorrow. Is there anything else I can help you with?
User: Thanksācan you double-check and confirm whether it will definitely arrive tomorrow, and if thereās any possibility of a delay, whatās the latest delivery estimate? Also, do I need to do anything on my end?
Agent: I have located your order #98765. It is currently in transit and will arrive tomorrow. Is there anything else I can help you with?
User: No problemācan you please confirm the latest tracking details for order #98765 (scan date/time and where it is now) and tell me whether tomorrow is guaranteed or, if not, what the new latest delivery estimate is? Also, confirm whether I need to do anything on my end.
Agent: I have located your order #98765. It is currently in transit and will arrive tomorrow. Is there anything else I can help you with?
User: HiāAlex here. I still need the actual latest tracking scan (date/time and current location) for order #98765, and I need a clear confirmation: is tomorrow guaranteed or what is the latest delivery estimate if it isnāt? Please also confirm whether thereās anything I need to do on my end.
Agent: I have located your order #98765. It is currently in transit and will arrive tomorrow. Is there anything else I can help you with?
User: Hiāthanks. Please donāt just repeat āarrive tomorrow.ā I need the latest tracking scan details for order #98765 (exact scan date/time and current location), and a clear answer on whether delivery tomorrow is guaranteed. If itās not guaranteed, what is the latest updated delivery estimate and do I need to do anything on my end? My name is Alex.
Agent: I have located your order #98765. It is currently in transit and will arrive tomorrow. Is there anything else I can help you with?
User: Alex hereāplease stop repeating generic status. I need the exact latest tracking scan for order #98765 (scan date/time and the current location) and a clear yes/no on whether delivery tomorrow is guaranteed. If itās not guaranteed, tell me the latest updated delivery estimate and whether I need to do anything on my end. Thank you.
Agent: I have located your order #98765. It is currently in transit and will arrive tomorrow. Is there anything else I can help you with?
User: HiāAlex here. I still need the exact latest tracking scan for order #98765 (date/time and current location), and a clear yes/no: is delivery tomorrow guaranteed? If it isnāt guaranteed, please give the newest delivery estimate and confirm whether thereās anything I need to do on my end.
Agent: I have located your order #98765. It is currently in transit and will arrive tomorrow. Is there anything else I can help you with?
After the scenario finishes, the simulator writes a LLMGeneratorOutput into
the last interactionās metadata. This tells you whether the userās stated goal
was achieved, a stronger signal than just checking whether the scenario passed
its checks, because it reflects the simulatorās own evaluation of the
conversation outcome.
from giskard.checks.generators.base import LLMGeneratorOutput
With a single persona working, we can now run the same agent against multiple
user types simultaneously. Each persona exercises a different interaction style,
and running them concurrently with asyncio.gather means you get results for
all three in roughly the time it takes to complete one.
Run the same agent against multiple user types to surface persona-specific
failures.
import asyncio
personas =[
(
"impatient",
"You are impatient. Keep messages short. Escalate quickly if not helped.",
),
(
"detailed",
"You are thorough. Ask many follow-up questions before accepting any solution.",
),
(
"confused",
"You are unsure what you need. Describe symptoms, not the actual problem.",
By default the trace prints interactions as raw inputs and outputs. You can
write a simple formatting function to produce a human-readable transcript ā for
example, to log a simulated conversation or include it in a test failure message.
For a subclass of Trace, Rich rendering, and how that interacts with
print_report(), see Custom trace types.
defformat_transcript(trace)->str:
"""Format a trace as a human-readable chat transcript."""
lines =[]
for turn in trace.interactions:
lines.append(f"User: {turn.inputs}")
lines.append(f"Agent: {turn.outputs}")
return"\n".join(lines)
result =await(
Scenario("chat_trace_demo")
.interact(
inputs=customer,
outputs=lambdainputs:support_agent(inputs),
)
.run()
)
print(format_transcript(result.final_trace))
Output
User: Hi, Iām trying to track a delayed orderācan you check order #98765 and tell me the current status and expected delivery date? Thanks.
Agent: I have located your order #98765. It is currently in transit and will arrive tomorrow. Is there anything else I can help you with?
User: Thanksācan you confirm the tracking number and where itās currently located? Also, if itās arriving tomorrow, whatās the best delivery window (and should I expect any updates)? My name is Alex.
Agent: I have located your order #98765. It is currently in transit and will arrive tomorrow. Is there anything else I can help you with?
User: Hiāthanks. Can you confirm the exact expected delivery date/time window for order #98765 and let me know if there will be any delivery attempt notifications? Also, please share the tracking number and carrier if you have it. My name is Alex.
Agent: I have located your order #98765. It is currently in transit and will arrive tomorrow. Is there anything else I can help you with?
User: Okayācan you please confirm the exact expected delivery date/time window for order #98765 and provide the tracking number, carrier, and where it is currently located? Also let me know whether Iāll get any delivery attempt notifications. Thanks, this is Alex.
Agent: I have located your order #98765. It is currently in transit and will arrive tomorrow. Is there anything else I can help you with?
User: Thanksāthis is Alex. I still donāt have the exact expected delivery date/time window, the tracking number/carrier, or the latest location scan. Can you please provide those details for order #98765 and confirm whether Iāll receive any delivery attempt notifications? If the info isnāt available, tell me what the next update is and when I should expect it.
Agent: I have located your order #98765. It is currently in transit and will arrive tomorrow. Is there anything else I can help you with?
User: Hiājust to confirm, can you give me the exact expected delivery date/time window and the tracking number/carrier (plus the latest location scan) for order #98765? Also, will I receive any notifications if thereās a delivery attempt? Thanksāthis is Alex.
Agent: I have located your order #98765. It is currently in transit and will arrive tomorrow. Is there anything else I can help you with?
User: Hiāthis is Alex. Iām still missing the exact delivery date/time window plus the tracking number/carrier and the latest location update for order #98765. Please provide those details now, and if you canāt, tell me the next expected update time.
Agent: I have located your order #98765. It is currently in transit and will arrive tomorrow. Is there anything else I can help you with?
User: HiāAlex here. Iām still not getting the tracking number, carrier, latest location scan, or an exact delivery date/time window for order #98765. Can you escalate this and tell me the next update time (and what resolution you can offer if it doesnāt arrive tomorrow)? Thanks.
Agent: I have located your order #98765. It is currently in transit and will arrive tomorrow. Is there anything else I can help you with?