- After each call, Jev sees the original request and its answer together. A
Noulquestion, which we call the gate, asks whether the request states an important fact about the customer that should be remembered. If P(yes) is at least 0.5, the ticket and Jev’s answer are saved as a memory for that customer. - A wrapper function,
ask_with_memory(), takes the samestateandquestionsarguments asask(), which is the TypeSafe Python SDKclient.system_onemethod with the model pinned and the call cached, and returns the Jev response. Before each call, it adds the customer’s saved tickets and Jev’s answers to them to the state.
ask_with_memory() takes the same arguments as ask() and returns the same
response, you can swap one for the other without changing any other code. The wrapper
finds the customer’s memories, adds them to the state and saves new ones itself.
The example sends five earlier tickets from two customers through the wrapper, then routes
three later messages from each customer twice: once with the memories it saved, once
without. A table puts the two answers side by side for all six.
Setup
TYPESAFE_API_KEY. Every API call is cached in
json_cache.json.
Download it into the folder you run this code from to replay the published numbers
instead of calling the API, or leave it out to run everything live.
Numbers below came from jev-1.13.0 on 2026-09-28.
The memory threshold of 0.5 is a starting point. You should evaluate it against
your own examples.
Define the tickets
Two customers, five earlier tickets and three later messages, all written for this cookbook. C-1042 (Harbor Logistics) runs the self-hosted edition on Windows Server under an Enterprise contract. C-2210 (Fernwood Studio) is on the cloud edition’s self-serve Team plan. Three of the earlier tickets state a lasting fact: an edition, a plan, a contract. Two don’t: a phone at the airport, a public holiday. No later message mentions the customer’s setup, so without memory Jev has to guess it. Each ticket becomes a state with two parts:customer, who the customer is, and
ticket, the ticket thread. The ticket_state() function builds a
simplified ticket, like one from a helpdesk. In your app, the state is each ticket as
your helpdesk sends it, and ask_with_memory() adds the customer’s saved tickets to it.
The split into earlier tickets and later messages is only for this example.
Route a ticket
OneChoice question picks the support team. The none_suitable option gives Jev an
answer for when no team fits, and a ticket with too little context can end up there.
The helper ask() is client.system_one with the model version fixed and every call
cached. It takes a state and a dict of questions and returns the SDK’s own response
object, so code that already reads client.system_one responses works with it unchanged.
Ask Jev whether the ticket is worth remembering
First,as_memory() pairs the original state with Jev’s answer: the memory the wrapper
may save. The request key
holds the state before memories were injected, and jev_answered maps each question
to its answer. This keeps old memories from being nested inside every new memory.
A second Jev call reads that pair. The gate asks whether the request
states an important fact about the customer, such as their edition, operating system, plan
or contract. Jev’s answer is there as context, but a fact that appears only in the
answer does not count. Without that rule, a generic answer such as “General product
questions” can outweigh a real fact in the request, and an answer that relied on an
earlier memory can be saved again as if it were new.
Wrap the call so it remembers
The wrapper,ask_with_memory(), has the same arguments and return value as ask(). The
memory store is a plain dict with one list per customer ID. The wrapper uses the ID in
the state to select the customer’s memories.
- Every call makes two sequential requests, your call followed by the memory gate. The gate judges the ticket together with Jev’s answer, so it runs after the routing request. If your gate ignores the answer, it could instead be a second question in the routing request (see fan-out).
- Memory only grows. Every saved memory goes into every later call for that customer. There is no size limit, no check for relevance and no expiry date here. The Next steps section has ideas for each.
- Your questions never mention the memories. The memories go into the state under
earlier_tickets_from_this_customer, and Jev reads the whole state. Nothing inROUTEchanges. - The state needs
customer.id. Plain Jev also accepts a string as the state, but this wrapper needs the ID to find the customer’s list.
Send the earlier tickets and watch the answers change
Send the five earlier tickets throughask_with_memory(), in the order they arrived. The
same customer sends two of the later messages again: slow dashboards and 20 more seats.
That shows how each saved memory changes Jev’s answers. The repeated messages go through
the wrapper too, so the gate judges them as well.
Route the same messages for both customers
Each customer now sends the three later messages. Each message goes to plainask() and
to ask_with_memory(), with the same state and the same question.
Open it in the playground
The link holds the exact routing state used for C-1042’s first slow-dashboards call, including its memories at that point, plus the routing question.Next steps
- Choose what your app should remember. Edit
GATEto describe what is worth remembering for your own task, and testREMEMBER_ATagainst examples you have labelled. - Choose which memories to add. The wrapper adds every saved memory. A relevance question can select a smaller set once the list gets long.
- Replace outdated memories. Ask whether a new memory replaces an older one, then remove the old entry in code when appropriate.
- Keep memories between runs. Replace
MEMORIESwith a database keyed by customer ID. The in-memory dict disappears when the process exits. - Act on the route. Map each team to a handler in code, such as booking a call for Enterprise customers or sending a setup-specific article. See intent routing and confidence-based routing. Add your reply to the ticket thread as a support message, and the gate can remember what you did.

