The desk: its tool and its answer
The desk reads a ticket, looks the order up and asks a model for the wording. This lesson builds it and traces one ticket through it.
It is the same desk you have traced since the first trace, written as a module other programs import. It starts with what it needs and the orders it knows.
"""The shop's support desk as a traced service."""
import re
from langfuse import get_client, observe, propagate_attributes
ORDERS = {"A17": "shipped on 3 March"}
FALLBACK = "You answer customers of a small online shop in one short sentence."
model = None # an OpenAI-compatible client, set by the program that runs the deskFALLBACK is the prompt text used when Langfuse has none. Keeping it in the file means the desk answers even when the server is unreachable.
@observe(name="lookup-order", as_type="tool")
def lookup_order(order_id):
status = ORDERS.get(order_id, "not found")
if status == "not found":
get_client().update_current_span(level="WARNING", status_message=f"no order {order_id}")
return statuslookup_order is the tool. A missing order is a warning rather than an error: the desk still answers, and the warning is on the observation for anyone reading the traces.
@observe(name="answer-ticket", as_type="agent")
def answer(ticket):
prompt = get_client().get_prompt("desk-system", fallback=FALLBACK)
order = re.search(r"[A-Z]\d{2}", ticket)
facts = f"\nLookup: {order.group()} {lookup_order(order.group())}" if order else ""
messages = [{"role": "system", "content": prompt.compile()}, {"role": "user", "content": ticket + facts}]
response = model.chat.completions.create(model="shop-model", messages=messages,
name="write-reply", langfuse_prompt=prompt)
return response.choices[0].message.contentanswer fetches the prompt from Langfuse with the fallback, calls the model through the traced OpenAI client, and returns the text. The decorator records it as one observation with the ticket as input.
print(support_desk.answer("Where is my order A17?"))
langfuse.flush()
local_langfuse.tree()python desk_once.pyThree observations: answer-ticket, with the lookup and the model call under it. The shape follows the calls, and the names are what every filter and dashboard in Langfuse groups by, so they are worth choosing deliberately.
- Ask about B22 and find the warning in
local_langfuse.SPANS. - Print the generation's
usage_detailsafter the run. - Change the fallback text and run again with no prompt in Langfuse.
Every expert started right here.