LangfuseLangfuse Python SDK 4.15.4 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
38 small wins to finish your pathNext lesson

What gets recorded: arguments and return values

@observe sends every argument and return value to Langfuse. capture_input=False stops that for one function, but a card number inside a customer's text still leaves.

Lesson 13 showed when data leaves the process. This lesson is about what leaves. The desk will take payments, and a card number is the kind of data that should never reach a tracing service.

Examplecard.py, after the setup lines with observe
import json


@observe(name="take-payment", as_type="tool")
def take_payment(card_number, amount):
    return f"charged {amount} euros"


take_payment("4111 1111 1111 1111", 40)
langfuse.flush()
print("card number exported:", "4111" in json.dumps([s["attributes"] for s in local_langfuse.SPANS]))
local_langfuse.tree("input")
Example
python card.py

The card number is in the observation's input, exactly as passed, and was exported. A decorated function's arguments become its input, and for this function that means the card.

Turning capture off

Examplecard.py, the changed decorator
@observe(name="take-payment", as_type="tool", capture_input=False)
Example
python card.py

capture_input=False leaves the input empty; capture_output=False does the same for the return value. LANGFUSE_OBSERVE_DECORATOR_IO_CAPTURE_ENABLED=false turns both off for every decorator at once. Better still, pass a reference such as a saved card's id, and look the number up inside the function, where nothing records it.

The card in the customer's words

Customers type card numbers into support tickets. The ticket is the agent's input and part of the model's messages.

Examplecard_ticket.py, after the setup lines and from desk import answer
import json

print(answer("My card 4111 1111 1111 1111 was charged twice for A17"))

langfuse.flush()
for span in local_langfuse.SPANS:
    print(span["name"], "contains the card:", "4111" in json.dumps(span["attributes"]))
Example
python card_ticket.py

Two of the three observations carry the card: the agent's input and the generation's input messages. Turning capture off there would remove what makes the trace useful, and the OpenAI wrapper from lesson 7 records messages whatever the decorator says. Changing the data as it leaves, lesson 15, fixes this for every observation at once.

Try it yourself
  • Return the card number from take_payment with capture_input=False still set, and search again.
  • Set LANGFUSE_OBSERVE_DECORATOR_IO_CAPTURE_ENABLED=false in the shell and run card_ticket.py.
  • Put an email address in the ticket and search the exported attributes for it.

This is what real progress feels like.