Tasks¶
A Task represents a unit of agent work—typically one turn in a conversation. Tasks track status, progress updates, results, and errors.
Creating Tasks¶
from redis_agent_kit import TaskManager
import redis.asyncio as redis
client = redis.from_url("redis://localhost:6379", decode_responses=True)
task_manager = TaskManager(client)
# Create a task linked to a session
task = await task_manager.create_task(
session_id="session_123",
message="What is Redis?",
)
print(task.task_id) # "01HXYZ..."
print(task.status) # TaskStatus.QUEUED
print(task.metadata["message"]) # "What is Redis?"
Task Lifecycle¶
Tasks progress through these statuses:
QUEUED → IN_PROGRESS → DONE
→ FAILED
→ CANCELLED
↓
AWAITING_INPUT → QUEUED (after submit_input)
AWAITING_CHILDREN → QUEUED (after last child terminates)
AWAITING_INPUT pauses the task for a user response (see Input Handling). AWAITING_CHILDREN pauses the task on spawned sub-tasks (see Sub-Tasks). Both unblock by re-enqueueing the task on the original queue.
Updating Tasks¶
Use update() to change status, add messages, set results, or set errors—in one call:
# Start processing with a message
await task_manager.update(task.task_id, status="in_progress", message="Starting...")
# Add progress updates
await task_manager.update(task.task_id, message="Found 5 documents")
await task_manager.update(task.task_id, message="Calling API", update_type="tool_call")
# Complete with result
await task_manager.update(task.task_id, status="done", result={"answer": "Redis is..."})
# Or fail with error
await task_manager.update(task.task_id, status="failed", error="API timeout")
Update types: info (default), tool_call, reflection, error
You can also use the individual convenience methods:
await task_manager.update_status(task.task_id, TaskStatus.IN_PROGRESS)
await task_manager.add_update(task.task_id, "Processing...")
await task_manager.set_result(task.task_id, {"answer": "..."})
await task_manager.set_error(task.task_id, "Something went wrong")
Retrieving Tasks¶
from redis_agent_kit import TaskStatus
# Get a single task
task = await task_manager.get_task(task_id)
print(task.status, task.result, task.updates)
# List tasks by status
tasks = await task_manager.list_tasks(status=TaskStatus.IN_PROGRESS)
for t in tasks:
print(f"{t.task_id}: {t.metadata.get('message')}")
# List tasks for a session
tasks = await task_manager.list_tasks(session_id=session_id)
TaskEmitter¶
For convenience, use TaskEmitter to emit updates without passing task_id everywhere:
from redis_agent_kit import TaskEmitter
emitter = TaskEmitter(task_manager, task.task_id)
# Fire-and-forget
emitter.emit_nowait("Processing query...")
# Awaitable
await emitter.emit("Analysis complete", metadata={"tokens": 150})
# Stream a single LLM token (ephemeral, not persisted)
await emitter.emit_token("Hello")
Watching Progress¶
Updates are persisted to the task and can be polled via get_task() or streamed live via Server-Sent Events when streaming is enabled:
from redis_agent_kit import AgentKit, StreamConfig
kit = AgentKit("redis://localhost:6379", agent_callable=my_handler, stream_config=StreamConfig(enabled=True))
Clients then connect to GET /tasks/{task_id}/stream to receive update, token, done, failed, and cancelled events in real time. See the Streaming guide for channel scopes, event filtering, and token streaming.
Deleting Tasks¶
Custom Prefix¶
All keys use rak: by default. Use a custom prefix:
task_manager = TaskManager(client, prefix="myapp")
# Keys: myapp:task:{id}, myapp:tasks:status:{status}
Task Fields¶
| Field | Type | Description |
|---|---|---|
task_id |
str | Unique ID (ULID) |
session_id |
str | Parent session ID |
status |
TaskStatus | Current status |
result |
dict | Result data |
error_message |
str | Error message |
updates |
list[TaskUpdate] | Progress updates |
metadata |
dict | Arbitrary metadata (includes message) |
input_request |
InputRequest | Pending input request |
input_response |
dict | User's input response |
parent_id |
str | None | Parent task ID (sub-tasking) |
spawn_key |
str | None | Stable label set by parent at spawn (sub-tasking) |
child_ids |
list[str] | Spawned children (sub-tasking) |
pending_children |
int | Non-terminal child count (sub-tasking) |
depth |
int | Nesting depth — 0 for root (sub-tasking) |
created_at |
datetime | Creation time |
updated_at |
datetime | Last update time |