STATEK
Warmup Code

STATEK Warmup Code

Warmup code is the startup phase of a STATEK job. It runs before the first normal LLM step and prepares the durable Python workspace the agent will use.

From the agent's perspective, warmup looks like prior work already done in the same Python session. If warmup sets user, prints the request, calls show_example(), or loads a document, the later model step sees that history before it writes its own Python.

That makes warmup powerful, but it should stay coherent. Warmup should connect directly to the agent's system prompt, available tools, expected variables, and next action. Do not surprise the agent with unexplained variables or hidden assumptions.

Prepare Request Context
user = message.sender
timestamp = message.created_at
request_text = message.text
 
print("Request:", request_text)
print("Timestamp:", timestamp)

The prompt for that agent should make those names unsurprising:

Describe Warmup Variables
You handle one queued user request at a time.
 
Available variables include `user`, `message`, `request_text`, and `timestamp`.
Use the printed request context before taking action.

Sources of Warmup

Warmup can come from more than one place:

  • agent-level warmup definitions for reusable startup behavior
  • job-level or dynamic warmup supplied when creating a job
  • parent-agent warmup, such as a dispatcher passing task-specific context or a selected default_example_id

When dynamic warmup and agent-level warmup are both present, the dynamic warmup runs first. This lets a dispatcher or parent job set task-specific names before the reusable agent warmup uses them.

For example, a parent can set default_example_id, then the child agent's normal warmup can call show_example() without hardcoding the example:

Pass a Default Example
# Parent-supplied dynamic warmup
default_example_id = selected_example_id
user = task.user
message = task.message
Load the Default Example
# Reusable agent-level warmup
list_of_examples() #STATEK: as tool
show_example() #STATEK: as tool
 
print("Request:", message.text)

Warmup Blocks

Warmup code can be split into logical blocks with a separator line containing at least 10 dashes:

Split Warmup Into Blocks
from datetime import datetime
 
now = datetime.now()
print("Current time:", now)
# ----------
user = message.sender
request_text = message.text
 
print("Request:", request_text)
# ----------
list_of_examples() #STATEK: as tool
show_example() #STATEK: as tool

Blocks execute in order. Each block's code and output become part of the job history unless the block is marked hidden. Use blocks to separate phases such as loading request context, listing examples, showing one example, printing task data, and loading docs.

This structure also makes history easier to inspect. Instead of one long startup script, the job shows the distinct preparation steps that led into the first model turn.

Tool-Call Warmup

A warmup line annotated with #STATEK: as tool is treated as a tool call attached to the warmup block:

Record Tool Calls in Warmup
list_of_examples() #STATEK: as tool
show_example(0) #STATEK: as tool

Use this for framework tools such as list_of_examples, show_example, list_of_documents, show_document, and docstr.

Tool-call warmup is useful when you want later chat history to contain a structured tool call and tool result instead of only Python console output. For example, an examples-first agent can start by listing examples, then showing the selected default example:

Show an Example as a Tool
list_of_examples() #STATEK: as tool
# ----------
show_example(default_example_id) #STATEK: as tool

Documentation warmup can use the same pattern:

Load API Documentation
docstr(DocumentSearchRequest) #STATEK: as tool
docstr(search_documents) #STATEK: as tool
# ----------
list_of_documents(topic="Search API") #STATEK: as tool
show_document("ranking rules", topic="Search API") #STATEK: as tool

The tool functions still need to be available to the job through the agent's tools, system tools, or context.

See Examples Machinery for list_of_examples() and show_example(...), and Documents Machinery for list_of_documents(...) and show_document(...).

Hidden Setup

Warmup blocks can include metadata. The common advanced case is hiding setup from model-facing history while still executing it:

Hide Runtime Setup
#STATEK: hidden = True
adapter = get_runtime_adapter("calendar")

Use hidden warmup sparingly. It should not create confusing state the model is expected to use without explanation. Hidden setup is better for plumbing, stable handles, and runtime adapters than for task facts, user instructions, selected examples, or data the agent must rely on.

Shared context can also be initialized in warmup when a job should read persisted preferences, entities, or vocabulary from earlier jobs:

Initialize Shared Context
init_shared_context(user)

Use read_only=True for workers that should see long-term context without writing to it. See Long-Term Memory for the provisional API and application-policy responsibilities.

Basic Context Warmup

A simple user-message job usually needs a few obvious names and a concise printout:

Print Basic Message Context
user = message.sender
timestamp = message.created_at
request_text = message.text
 
print("User:", user.display_name)
print("Time:", timestamp)
print("Request:", request_text)

Prefer printing exactly what the agent should rely on. Avoid dumping entire user profiles, credentials, raw webhook payloads, or private objects the task does not need.

Current Time and Request

Many agents need current time as part of context. Keep the format explicit:

Print Current UTC Time
from datetime import datetime, timezone
 
now = datetime.now(timezone.utc)
print("Current UTC time:", now.isoformat())
print("Request:", message.text)

If user-local time matters, pass or compute it deliberately:

Print User-Local Time
local_time = user.timezone.convert(now)
print("Current user-local time:", local_time.isoformat())

Examples-First Startup

Examples are useful when they match the prompt and the current task. A common pattern is to show available examples, then show one selected example:

Start With Matching Examples
list_of_examples() #STATEK: as tool
# ----------
show_example(default_example_id) #STATEK: as tool
# ----------
print("Request:", message.text)

If the example is chosen by a dispatcher, make that visible:

Print the Selected Example ID
print("Selected example id:", default_example_id)
show_example(default_example_id) #STATEK: as tool

Do not use examples as a hidden behavior switch. The prompt should still explain the agent's role, tool surface, and expected output.

Documentation Startup

Agents that operate on a narrow API or object model can start with relevant docs:

Inspect API Docs During Warmup
docstr(ReportRequest) #STATEK: as tool
docstr(generate_report) #STATEK: as tool
# ----------
print("Dataset:", dataset.name)
print("Requested report:", request_text)

For document collections:

Show Relevant Documents
list_of_documents(topic="Reports") #STATEK: as tool
show_document("allowed filters", topic="Reports") #STATEK: as tool

Keep this focused. Loading too much documentation can bury the actual request and make the first model step less reliable.

For document file format, topic lookup, audience filtering, and line slicing, see Documents Machinery.

Dispatcher Startup

A dispatcher or coordinator warmup can show available agents, recent context, and candidate example ids before asking the model to route work:

Print Dispatcher Inputs
agents = find_agents()
recent_threads = find_recent_threads(user, limit=5)
candidate_examples = rank_examples(message.text, limit=3)
 
print("Available agents:", list(agents.keys()))
print("Recent thread ids:", [thread.id for thread in recent_threads])
print("Candidate example ids:", candidate_examples)
print("Request:", message.text)

The dispatcher should pass only the durable context the child job needs. The child gets its own Python workspace and history:

Build Child Warmup
selected_agent = agents["research_assistant"]
selected_example_id = candidate_examples[0]
 
child_warmup = f"""
default_example_id = {selected_example_id}
user = task.user
message = task.message
"""

In real code, prefer passing durable objects, ids, or structured job context over string interpolation for arbitrary user data.

For a fuller dispatcher and worker warmup example, see Practical Examples.

Multi-Block Pattern

This is a fuller warmup layout for a request-processing specialist:

Compose a Multi-Block Startup
from datetime import datetime, timezone
 
now = datetime.now(timezone.utc)
print("Current UTC time:", now.isoformat())
# ----------
user = task.user
message = task.message
request_text = message.text
 
print("User:", user.display_name)
print("Request:", request_text)
# ----------
list_of_examples() #STATEK: as tool
show_example(default_example_id) #STATEK: as tool
# ----------
list_of_documents(topic="Request Handling") #STATEK: as tool
show_document("escalation rules", topic="Request Handling") #STATEK: as tool
# ----------
account = load_account(user.account_id)
print("Account status:", account.status)
print("Next action: inspect the request and choose the safest supported operation.")

Each block has one purpose. The final print nudges the agent toward the next action without inventing a hidden workflow.

Queue-Picking Warmup

Warmup can also pick the next unit of work for a bounded worker job:

Pick the Next Queue Task
task = pick_next_task()
# ----------
user = task.user
message = task.message
timestamp = task.created_at
request_text = message.text
 
print("Task id:", task.id)
print("Request:", request_text)

If pick_next_task() is implemented as a temporal function and no task is ready, the job can remain in warmup while STATEK waits for the future-like result. This can be useful for controlled worker orchestration where the application bounds the number of jobs allowed to wait this way.

⚠️

Use temporal warmup for bounded orchestration patterns such as controlled queue-picking, not as the default model for broad user-facing event delivery. For human input, webhooks, external completions, and product-facing interruptions, prefer callbacks, events, and queues unless a future is specifically the right fit.

See Temporal Tools for the @temporal mechanics behind this pattern, including FutureResult, readiness conditions, and combined futures.

Practical Rules

Keep warmup short, purposeful, and prompt-aligned. The agent should understand why each variable exists and what it should do next.

Print only what the agent should rely on. Avoid secrets, credentials, unnecessary private data, large raw payloads, or noisy object dumps.

Prefer stable handles and durable objects over transient clients. A warmup block can place account_id, document_id, or a dbzero-backed object in the workspace; process-local SDK clients and open connections belong in application services, agent context, or hidden/internal tools.

Use visible warmup for task facts, selected examples, request text, and docs. Use hidden warmup only for setup that should not become part of the model-facing story.

Use callbacks and events for broad interruption flows. Use temporal warmup only when queue-picking or bounded orchestration belongs naturally inside the startup phase of a durable Python job.