Agents can take an unpredictable amount of time to do their work — an LLM tool-calling loop might finish in seconds or run for hours depending on the task. Tensorlake handles this by letting functions run indefinitely as long as they keep sending heartbeats in the form of progress updates. A timeout only kicks in if a function stops making progress — it doesn’t finish within the allotted time and it doesn’t send any progress updates to reset the clock.
Setting Timeouts
Set the timeout attribute on the @function() decorator to control how long a function can run before it is terminated and marked as failed.
from tensorlake.applications import function
@function(timeout=1800) # 30 minutes
def deep_research(prompt: str) -> str:
...
| Value |
|---|
| Default | 300 (5 minutes) |
| Minimum | 1 second |
| Maximum | 172800 (48 hours) |
When a function times out, it is terminated and marked as failed. If the function has a retry policy, it will be retried according to that policy.
Automatic Timeout Reset
When a function reports progress via ctx.progress.update(), its timeout automatically resets. This allows functions to run indefinitely as long as they continue making progress.
from tensorlake.applications import function, RequestContext
@function(timeout=300) # 5 minute timeout
def long_running_task(items: list) -> dict:
ctx = RequestContext.get()
# After 3 minutes of processing...
ctx.progress.update(50, 100, "Halfway done")
# Timeout just reset to 5 minutes from NOW
# Function can run another 5 minutes before next update
# Continue processing...
Timeline:
- Function starts with 5 minute timeout
- At 3 minutes:
progress.update() called
- Timeout resets to 5 minutes from this point
- Function can now run until minute 8 (3 + 5)
- Next
progress.update() resets timeout again
Set a short timeout (e.g., 5 minutes) and rely on progress updates to extend it. This way, if a function gets stuck and stops reporting progress, it fails fast instead of running silently for hours.
Examples
Agent Loops
An agent that runs hundreds of iterations can use a short timeout per iteration. Each progress update resets the clock:
@function(timeout=300) # 5 minute timeout per iteration
def persistent_agent(task: str) -> str:
ctx = RequestContext.get()
for iteration in range(1000):
ctx.progress.update(iteration, 1000) # resets timeout
result = agent_iteration(task)
if is_complete(result):
return result
Batch Processing
Process an unbounded stream of items. The function runs as long as items keep arriving:
@function(timeout=600) # 10 minute timeout
def process_stream(stream_url: str) -> dict:
ctx = RequestContext.get()
count = 0
for item in stream_items(stream_url):
ctx.progress.update(count, count + 1, f"Processed {count} items")
process(item)
count += 1
return {"total": count}
Video/Audio Processing
Report progress every N frames to keep the timeout from firing during long media processing:
@function(timeout=300)
def process_video(video_url: str) -> str:
ctx = RequestContext.get()
frames = extract_frames(video_url)
total_frames = len(frames)
for i, frame in enumerate(frames):
if i % 100 == 0:
ctx.progress.update(i, total_frames, f"Processing frame {i}/{total_frames}")
process_frame(frame)
return "complete"
Learn More