Earlier tutorials tested a plain function and a single LLM call. Real agents add
a moving part: they decide when to call a tool. A correct-looking answer that
was hallucinated instead of retrieved is still a bug, so an agent test has to
cover both the output and the behaviour that produced it.
SemanticSimilarity and any LLM-based check need a configured model. This is
separate from the model the agent uses β the system under test and the
evaluator are deliberately independent.
from giskard.checks import set_default_generator
from giskard.agents.generators import Generator
from giskard.agents.embeddings import EmbeddingModel
One tool, one instruction. The tool appends to TOOL_CALLS so the test can
later assert it ran β a two-line spy that needs no patching and keeps the real
tool behaviour intact.
from agents import(
Agent,
Runner,
function_tool,
set_default_openai_api,
set_default_openai_client,
set_tracing_disabled,
)
from openai import AsyncAzureOpenAI
# Point the Agents SDK at Azure OpenAI instead of the default OpenAI client.
set_default_openai_client(
AsyncAzureOpenAI(
api_key=os.environ["AZURE_AI_API_KEY"],
azure_endpoint=os.environ["AZURE_AI_ENDPOINT"],
api_version="2024-10-21",
)
)
set_default_openai_api("chat_completions")
set_tracing_disabled(True)
TOOL_CALLS:list[tuple[str,str]]=[]
@function_tool
defget_order_status(order_id:str)->str:
"""Return the shipping status for an order id."""
TOOL_CALLS.append(("get_order_status", order_id))
returnf"Order {order_id} shipped on 2024-05-01, arriving in 2 days."
support_agent =Agent(
name="Support",
instructions=(
"You are a customer support agent. "
"Always use the get_order_status tool to answer order questions. "
The callable you hand to .interact() must accept a parameter named inputs
(or trace) β those are the names Giskard Checks injects. An async def
callable is awaited for you, which is what you want with Runner.run:
Runner.run_sync would fail inside the already-running event loop of a
notebook or a test.
Clearing TOOL_CALLS at the start of each run keeps assertions scoped to the
current interaction.
StringMatching β cheap, deterministic: the order id must be echoed back.
SemanticSimilarity β tolerant of phrasing: the answer must mean roughly
what the tool returned.
FnCheck β the behavioural assertion: the tool was actually called.
The FnCheck is the one that catches a hallucinating agent. Without it, an
agent that invents a plausible shipping date can still pass every text check.
from giskard.checks import FnCheck, Scenario, SemanticSimilarity, StringMatching
scenario =(
Scenario("order_status_lookup")
.interact(
inputs="Where is my order A123?",
outputs=run_support_agent,
)
.check(
StringMatching(
name="mentions_order_id",
keyword="A123",
text_key="trace.last.outputs",
)
)
.check(
SemanticSimilarity(
embedding_model=embedding_model,
name="matches_tool_result",
reference_text="Order A123 shipped on 2024-05-01 and arrives in 2 days.",
threshold=0.6,
)
)
.check(
FnCheck(
name="called_get_order_status",
fn=lambdatrace:any(call[0]=="get_order_status"for call in TOOL_CALLS),
ββββββββββββββββββββββββββββββββββββββββββββββββββββ β PASSED ββββββββββββββββββββββββββββββββββββββββββββββββββββmentions_order_idPASSmatches_tool_resultPASScalled_get_order_statusPASSββββββββββββββββββββββββββββββββββββββββββββββββββββββ Trace ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ Interaction 1 ββββββββββββββββββββββββββββββββββββββββββββββββββ
Inputs: 'Where is my order A123?'
Outputs: 'Your order A123 shipped on May 1, 2024, and is expected to arrive in 2 days.'ββββββββββββββββββββββββββββββββββββββββββ 1 step in 3358ms | runs: 1/1 βββββββββββββββββββββββββββββββββββββββββββ
Knowing that the tool ran is often not enough β you also want the agent to
have passed the right argument. TOOL_CALLS records both, so a second
FnCheck covers it.
ββββββββββββββββββββββββββββββββββββββββββββββββββββ β PASSED ββββββββββββββββββββββββββββββββββββββββββββββββββββcalled_with_b777PASSββββββββββββββββββββββββββββββββββββββββββββββββββββββ Trace ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ Interaction 1 ββββββββββββββββββββββββββββββββββββββββββββββββββ
Inputs: 'Can you check order B777 for me?'
Outputs: 'Order B777 shipped on May 1, 2024, and is expected to arrive in 2 days. If you have any more questions, feel free to ask!'ββββββββββββββββββββββββββββββββββββββββββ 1 step in 3201ms | runs: 1/1 βββββββββββββββββββββββββββββββββββββββββββ