Skip to main content
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
Default300 (5 minutes)
Minimum1 second
Maximum172800 (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:
  1. Function starts with 5 minute timeout
  2. At 3 minutes: progress.update() called
  3. Timeout resets to 5 minutes from this point
  4. Function can now run until minute 8 (3 + 5)
  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