Sessions & scheduling¶
Session management, transports, task lifecycle objects, and the job scheduler for running background and recurring work.
session
¶
Streaming session orchestration for bidirectional tasks.
SessionManager
¶
SessionManager(*, limits: SessionLimits | None = None, state_store: SessionStateStore | StateStore | None = None, control_policy: ControlPolicy | None = None, telemetry_sink: TaskTelemetrySink | None = None)
Registry for StreamingSession instances by session_id.
get_or_create
async
¶
get_or_create(session_id: str) -> StreamingSession
Return the existing session for session_id, creating and hydrating one if needed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session_id
|
str
|
The session identifier to look up or create. |
required |
Returns:
| Type | Description |
|---|---|
StreamingSession
|
The (possibly newly created) :class: |
StreamingSession
|
configured state store. |
get
async
¶
get(session_id: str) -> StreamingSession | None
Return the session for session_id if it already exists, without creating one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session_id
|
str
|
The session identifier to look up. |
required |
Returns:
| Type | Description |
|---|---|
StreamingSession | None
|
The existing :class: |
drop
async
¶
drop(session_id: str) -> None
Remove and close the session for session_id, if it exists.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session_id
|
str
|
The session identifier to remove. |
required |
SessionLimits
dataclass
¶
SessionLimits(max_tasks_per_session: int = 8, max_background_tasks: int = 4, max_concurrent_tasks: int = 3, max_task_runtime_s: float | None = 900, update_queue_size: int = 500, steering_queue_size: int = 200, max_pending_patches: int = 32, max_steering_payload_bytes: int = MAX_STEERING_PAYLOAD_BYTES, max_steering_events_per_task: int = 512)
Resource and safety limits enforced by a :class:StreamingSession.
Attributes:
| Name | Type | Description |
|---|---|---|
max_tasks_per_session |
int
|
Maximum number of non-terminal tasks a session may hold at once. |
max_background_tasks |
int
|
Maximum number of non-terminal background tasks per session. |
max_concurrent_tasks |
int
|
Maximum number of tasks executing concurrently (via a semaphore);
|
max_task_runtime_s |
float | None
|
Wall-clock timeout applied to each task pipeline, or |
update_queue_size |
int
|
Maximum size of the update broker's per-subscriber queues. |
steering_queue_size |
int
|
Maximum size of each task's steering-event inbox. |
max_pending_patches |
int
|
Maximum number of context patches awaiting human approval at once. |
max_steering_payload_bytes |
int
|
Maximum allowed size of a steering event payload, in bytes. |
max_steering_events_per_task |
int
|
Maximum number of recently-seen event IDs tracked per task for duplicate detection. |
StreamingSession
¶
StreamingSession(session_id: str, *, control_policy: ControlPolicy | None = None, limits: SessionLimits | None = None, state_store: SessionStateStore | StateStore | None = None, telemetry_sink: TaskTelemetrySink | None = None)
Manages bidirectional communication and task lifecycle.
A StreamingSession owns the tasks, steering inboxes, update broker, task groups,
and shared conversation context for a single session_id. It is the primary runtime
surface used by transports (connect), planner-facing meta-tools (spawning and
steering tasks), and background-task orchestration (context patches, proactive
reporting, and task groups). Instances are typically created and cached via
:class:SessionManager rather than constructed directly.
registry
property
¶
registry: TaskRegistry
Return the :class:TaskRegistry tracking task state for this session.
limits
property
¶
limits: SessionLimits
Return the :class:SessionLimits configuration governing this session.
pending_patches
property
¶
pending_patches: dict[str, PendingContextPatch]
Return a snapshot copy of patches awaiting human approval, keyed by patch_id.
context_version
property
¶
context_version: int
Return the monotonically increasing version counter for the session context.
context_hash
property
¶
context_hash: str | None
Return the SHA-256 hash of the current llm_context, or None if unset.
get_context
¶
get_context() -> tuple[dict[str, Any], dict[str, Any]]
Return copies of the session's current context dicts.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
A |
dict[str, Any]
|
mutate without affecting session state. |
get_background_results
¶
get_background_results() -> dict[str, BackgroundTaskResult]
Return a copy of completed background task results, keyed by task_id.
Returns:
| Type | Description |
|---|---|
dict[str, BackgroundTaskResult]
|
A shallow copy of the session's |
configure_background_tasks
¶
configure_background_tasks(config: BackgroundTasksConfig | None = None, **overrides: Any) -> BackgroundTasksConfig
Configure runtime background task behavior.
get_background_task_config
¶
get_background_task_config() -> BackgroundTasksConfig
Return the active :class:BackgroundTasksConfig, creating a default one if unset.
Returns:
| Type | Description |
|---|---|
BackgroundTasksConfig
|
The current background-task configuration for this session. |
set_foreground_busy
¶
set_foreground_busy(*, busy: bool) -> None
Mark whether the foreground turn is currently busy or idle.
This gates the proactive reporter: reports are only generated while the foreground is idle.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
busy
|
bool
|
|
required |
on_foreground_yield
async
¶
on_foreground_yield(*, turn_id: str | None = None) -> int
Handle the foreground yielding control, auto-sealing open task groups if configured.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
turn_id
|
str | None
|
The turn whose open groups should be sealed. Defaults to the session's
current turn (see |
None
|
Returns:
| Type | Description |
|---|---|
int
|
The number of task groups sealed. Always |
int
|
|
suppress_proactive_reports
¶
suppress_proactive_reports(*, task_ids: Iterable[str] | None = None, group_id: str | None = None) -> int
Suppress future proactive reports for the given tasks and/or group.
Once suppressed, matching task/group completions will not enqueue proactive report requests (e.g. because their results were already consumed by a retained turn).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_ids
|
Iterable[str] | None
|
Task IDs to suppress individually. |
None
|
group_id
|
str | None
|
A group ID to suppress as a whole. |
None
|
Returns:
| Type | Description |
|---|---|
int
|
The number of newly-added suppressions (already-suppressed entries are not |
int
|
counted again). |
schedule_group_continuation
¶
schedule_group_continuation(*, group_id: str, timeout_s: float | None, max_hops: int, cooldown_s: float) -> None
Schedule a background waiter that keeps polling a group after a retain-turn timeout.
Repeatedly waits for the group's completion (up to max_hops times, sleeping
cooldown_s between attempts) so a group that timed out while retaining the
turn is still tracked to completion. A no-op if a continuation for this group
is already scheduled and running.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
group_id
|
str
|
The task group to keep waiting on. |
required |
timeout_s
|
float | None
|
Per-attempt wait timeout in seconds, or |
required |
max_hops
|
int
|
Maximum number of wait attempts; scheduling is skipped entirely if |
required |
cooldown_s
|
float
|
Seconds to sleep between attempts when the previous attempt timed out. |
required |
connect
async
¶
connect(transport: Transport) -> SessionConnection
Bind a :class:Transport to this session.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
transport
|
Transport
|
The transport implementation used to send/receive messages for this session. |
required |
Returns:
| Type | Description |
|---|---|
SessionConnection
|
A new :class: |
hydrate
async
¶
hydrate() -> None
Load persisted tasks from the state store into the in-memory registry.
Idempotent: subsequent calls after the first successful hydration are no-ops. Restores the most recent foreground task ID from the loaded tasks, if any.
update_context
¶
update_context(*, llm_context: dict[str, Any] | None = None, tool_context: dict[str, Any] | None = None) -> None
Replace the session's llm_context and/or tool_context.
Any legacy inline background_results/background_result entries found in
llm_context are extracted into the session's dedicated background-results
store. Bumps context_version and recomputes context_hash whenever
llm_context is provided.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
llm_context
|
dict[str, Any] | None
|
Replacement dict for the LLM-facing context, or |
None
|
tool_context
|
dict[str, Any] | None
|
Replacement dict for the tool-facing context, or |
None
|
configure_proactive_reporting
¶
configure_proactive_reporting(*, generator: Callable[[ProactiveReportRequest], Awaitable[None]], enabled: bool = False, strategies: list[str] | None = None, max_queued: int = 5, timeout_s: float = 30.0, max_hops: int = 2, fallback_notification: bool = True) -> None
Configure proactive report-back for background task completions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
generator
|
Callable[[ProactiveReportRequest], Awaitable[None]]
|
Async callable to generate proactive messages. |
required |
enabled
|
bool
|
Master switch for proactive reporting. |
False
|
strategies
|
list[str] | None
|
Merge strategies that trigger reports (default: APPEND, REPLACE). |
None
|
max_queued
|
int
|
Maximum queued reports before dropping oldest. |
5
|
timeout_s
|
float
|
Timeout for proactive message generation. |
30.0
|
max_hops
|
int
|
Maximum proactive recursion hops before disabling background spawning. |
2
|
fallback_notification
|
bool
|
Fall back to notification panel if generation fails. |
True
|
ensure_capacity
async
¶
ensure_capacity(task_type: TaskType) -> None
Verify the session has room for another task of the given type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_type
|
TaskType
|
The task type ( |
required |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
With |
spawn_task
async
¶
spawn_task(pipeline: TaskPipeline, *, task_type: TaskType = TaskType.FOREGROUND, priority: int = 0, context_snapshot: TaskContextSnapshot | None = None, description: str | None = None, spawn_reason: str | None = None, parent_task_id: str | None = None, spawned_from_event_id: str | None = None, query: str | None = None, task_id: str | None = None, trace_id: str | None = None, merge_strategy: MergeStrategy = MergeStrategy.APPEND, propagate_on_cancel: Literal['cascade', 'isolate'] = 'cascade', notify_on_complete: bool = True, group_id: str | None = None) -> str
Create a task and run its pipeline concurrently, returning immediately.
Registers the task in the registry, builds (or adapts) its context snapshot,
creates its steering inbox, and schedules pipeline on a background
asyncio.Task without waiting for it to finish. Use this for background
tasks, or for foreground tasks whose completion is awaited elsewhere.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pipeline
|
TaskPipeline
|
The async callable that executes the task given a :class: |
required |
task_type
|
TaskType
|
Whether this is a |
FOREGROUND
|
priority
|
int
|
Scheduling priority hint stored on the task. |
0
|
context_snapshot
|
TaskContextSnapshot | None
|
An explicit context snapshot to use instead of building one from the session's current context. |
None
|
description
|
str | None
|
Human-readable description of the task, used in summaries and notifications. |
None
|
spawn_reason
|
str | None
|
Machine-readable reason the task was spawned (e.g. |
None
|
parent_task_id
|
str | None
|
The task that spawned this one, if any. |
None
|
spawned_from_event_id
|
str | None
|
The steering/event ID that triggered this spawn, if any. |
None
|
query
|
str | None
|
The user-facing query this task is answering, if applicable. |
None
|
task_id
|
str | None
|
Explicit task ID to use; a random one is generated if omitted. |
None
|
trace_id
|
str | None
|
Trace ID to associate with the task's updates. |
None
|
merge_strategy
|
MergeStrategy
|
Strategy used to merge the task's resulting context patch. |
APPEND
|
propagate_on_cancel
|
Literal['cascade', 'isolate']
|
Whether cancelling this task cascades to its children
( |
'cascade'
|
notify_on_complete
|
bool
|
Whether a default completion notification is emitted when the task finishes without an explicit notification. |
True
|
group_id
|
str | None
|
Task group to associate this task's completion with, if any. |
None
|
Returns:
| Type | Description |
|---|---|
str
|
The task ID (either |
run_task
async
¶
run_task(pipeline: TaskPipeline, *, task_type: TaskType = TaskType.FOREGROUND, priority: int = 0, context_snapshot: TaskContextSnapshot | None = None, description: str | None = None, spawn_reason: str | None = None, parent_task_id: str | None = None, spawned_from_event_id: str | None = None, query: str | None = None, task_id: str | None = None, trace_id: str | None = None, merge_strategy: MergeStrategy = MergeStrategy.APPEND, propagate_on_cancel: Literal['cascade', 'isolate'] = 'cascade', notify_on_complete: bool = True) -> TaskResult
Create a task and run its pipeline to completion, awaiting the result.
Unlike :meth:spawn_task, this awaits the pipeline directly and returns its
:class:TaskResult. When task_type is FOREGROUND, the foreground-busy
flag is set for the duration of the call and on_foreground_yield is invoked
once the pipeline finishes (success, failure, or cancellation).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pipeline
|
TaskPipeline
|
The async callable that executes the task given a :class: |
required |
task_type
|
TaskType
|
Whether this is a |
FOREGROUND
|
priority
|
int
|
Scheduling priority hint stored on the task. |
0
|
context_snapshot
|
TaskContextSnapshot | None
|
An explicit context snapshot to use instead of building one from the session's current context. |
None
|
description
|
str | None
|
Human-readable description of the task, used in summaries and notifications. |
None
|
spawn_reason
|
str | None
|
Machine-readable reason the task was spawned. |
None
|
parent_task_id
|
str | None
|
The task that spawned this one, if any. |
None
|
spawned_from_event_id
|
str | None
|
The steering/event ID that triggered this spawn, if any. |
None
|
query
|
str | None
|
The user-facing query this task is answering, if applicable. |
None
|
task_id
|
str | None
|
Explicit task ID to use; a random one is generated if omitted. |
None
|
trace_id
|
str | None
|
Trace ID to associate with the task's updates. |
None
|
merge_strategy
|
MergeStrategy
|
Strategy used to merge the task's resulting context patch. |
APPEND
|
propagate_on_cancel
|
Literal['cascade', 'isolate']
|
Whether cancelling this task cascades to its children
( |
'cascade'
|
notify_on_complete
|
bool
|
Whether a default completion notification is emitted when the task finishes without an explicit notification. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
The |
TaskResult
|
class: |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If session/task-type limits are exceeded (see |
TimeoutError
|
If the pipeline exceeds |
SteeringCancelled
|
If the task is cancelled via steering while running. |
steer
async
¶
steer(event: SteeringEvent) -> bool
Process an inbound steering event against this session's tasks.
Handles the full steering lifecycle: session/validation checks, duplicate-event
detection, persistence, approve/reject routing for pending context patches and
gated controls, control-policy confirmation gating (emitting a CHECKPOINT
update when confirmation is required), and dispatch of PRIORITIZE, PAUSE,
RESUME, and CANCEL (including cascading cancellation to child tasks).
Finally, the event is pushed onto the target task's steering inbox if one exists.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
SteeringEvent
|
The steering event to process. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
bool
|
task's steering inbox); |
bool
|
targeted a different session, or is pending confirmation. |
get_task
async
¶
get_task(task_id: str) -> TaskState | None
Look up a task's current state by ID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_id
|
str
|
The task to look up. |
required |
Returns:
| Type | Description |
|---|---|
TaskState | None
|
The task's :class: |
list_tasks
async
¶
list_tasks(*, status: TaskStatus | None = None) -> list[TaskState]
List tasks belonging to this session.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
status
|
TaskStatus | None
|
If provided, only return tasks with this status. |
None
|
Returns:
| Type | Description |
|---|---|
list[TaskState]
|
The matching list of :class: |
cancel_task
async
¶
cancel_task(task_id: str, *, reason: str | None = None) -> bool
Request cancellation of a task by sending a CANCEL steering event.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_id
|
str
|
The task to cancel. |
required |
reason
|
str | None
|
Optional human-readable reason recorded on the cancellation. |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
|
broadcast_steer
async
¶
broadcast_steer(*, event_type: SteeringEventType, payload: dict[str, Any] | None = None, source: str = 'user') -> int
Send the same steering event to every active task in this session.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_type
|
SteeringEventType
|
The steering event type to broadcast (e.g. |
required |
payload
|
dict[str, Any] | None
|
Payload to attach to each event. |
None
|
source
|
str
|
The |
'user'
|
Returns:
| Type | Description |
|---|---|
int
|
The number of tasks that accepted the event (see :meth: |
list_updates
async
¶
list_updates(*, task_id: str | None = None, since_id: str | None = None, limit: int = 500) -> list[StateUpdate]
Fetch persisted state updates for this session from the state store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_id
|
str | None
|
If provided, only return updates for this task. |
None
|
since_id
|
str | None
|
If provided, only return updates after this update ID. |
None
|
limit
|
int
|
Maximum number of updates to return. |
500
|
Returns:
| Type | Description |
|---|---|
list[StateUpdate]
|
The matching list of :class: |
list[StateUpdate]
|
by the underlying state store. |
subscribe
async
¶
subscribe(*, task_ids: list[str] | None = None, update_types: list[UpdateType] | None = None, since_id: str | None = None) -> AsyncIterator[StateUpdate]
Subscribe to live state updates for this session, optionally replaying history.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_ids
|
list[str] | None
|
If provided, only yield updates for these task IDs. |
None
|
update_types
|
list[UpdateType] | None
|
If provided, only yield updates of these types. |
None
|
since_id
|
str | None
|
If provided (and exactly one |
None
|
Returns:
| Type | Description |
|---|---|
AsyncIterator[StateUpdate]
|
An async iterator of :class: |
AsyncIterator[StateUpdate]
|
The subscription is automatically released when the iterator is closed or |
AsyncIterator[StateUpdate]
|
fully consumed. |
apply_context_patch
async
¶
apply_context_patch(*, patch: ContextPatch, strategy: MergeStrategy = MergeStrategy.APPEND, payload: Any | None = None, group_id: str | None = None) -> str | None
Merge a completed task's context patch into the session, per strategy.
Detects whether the patch was produced from a context version/hash older than
the session's current one (context_diverged) and emits a warning notification
when so. For HUMAN_GATED, the patch is queued for approval and a CHECKPOINT
update is published instead of being applied immediately. For APPEND/REPLACE,
the patch is recorded as a background result immediately.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
patch
|
ContextPatch
|
The context patch produced by the completed task. |
required |
strategy
|
MergeStrategy
|
The merge strategy to apply. |
APPEND
|
payload
|
Any | None
|
The task's raw result payload, stored alongside the patch for
|
None
|
group_id
|
str | None
|
The task group this patch's task belongs to, if any. |
None
|
Returns:
| Type | Description |
|---|---|
str | None
|
The generated |
str | None
|
( |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If the number of pending patches would exceed
|
mark_background_consumed
async
¶
mark_background_consumed(*, task_ids: list[str]) -> int
Remove background task results from session context by task_id.
apply_pending_patch
async
¶
apply_pending_patch(*, patch_id: str, strategy: MergeStrategy | None = None) -> bool
Approve and merge a previously human-gated pending context patch.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
patch_id
|
str
|
The ID of the pending patch to apply (see |
required |
strategy
|
MergeStrategy | None
|
Merge strategy to apply the patch with; defaults to |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
|
bool
|
pending patch exists for |
close
async
¶
close() -> None
Shut down the session, cancelling all in-flight tasks and background helpers.
Cancels the proactive reporter task, any scheduled group-continuation tasks, and
every running task handle (marking each corresponding task as CANCELLED with
error "session_closed"). Clears internal task-handle and steering-inbox
tracking. Intended to be called once when a session is being torn down (see
:meth:SessionManager.drop).
resolve_or_create_group
async
¶
resolve_or_create_group(*, group_name: str | None = None, group_id: str | None = None, turn_id: str | None = None, merge_strategy: MergeStrategy | None = None, report_strategy: GroupReportStrategy | None = None, retain_turn: bool = False) -> TaskGroup
Resolve an existing group or create a new one based on name/ID.
Turn-scoped name resolution: - If group_id provided, join that exact group (error if not found/joinable) - If group_name provided, resolve to OPEN group with that name created in the same turn, or create new group if none exists
add_task_to_group
async
¶
add_task_to_group(group_id: str, task_id: str) -> bool
Add a task to a group. Returns False if group not found or not open.
seal_group
async
¶
seal_group(group_id: str) -> bool
Seal a group (no more tasks can join). Returns False if already sealed.
get_group
async
¶
get_group(group_id: str | None = None, *, group_name: str | None = None, turn_id: str | None = None) -> TaskGroup | None
Get a task group by ID or by name+turn resolution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
group_id
|
str | None
|
Direct lookup by group ID |
None
|
group_name
|
str | None
|
Name-based lookup (requires turn_id for disambiguation) |
None
|
turn_id
|
str | None
|
Turn ID for name-based lookup |
None
|
list_groups
async
¶
list_groups(*, status: GroupStatus | None = None) -> list[TaskGroup]
List all task groups, optionally filtered by status.
mark_task_complete_in_group
async
¶
mark_task_complete_in_group(group_id: str, task_id: str, *, success: bool, patch: ContextPatch | None = None, patch_id: str | None = None) -> None
Mark a task as complete (success or failure) within its group.
wait_for_group_completion
async
¶
wait_for_group_completion(group_id: str, *, timeout_s: float | None = None) -> tuple[TaskGroup | None, bool]
Wait for a group to complete.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
group_id
|
str
|
The group to wait for. |
required |
timeout_s
|
float | None
|
Maximum time to wait in seconds. If None, wait indefinitely. |
None
|
Returns:
| Type | Description |
|---|---|
TaskGroup | None
|
A tuple of (group, timed_out). If timed_out is True, the group may |
bool
|
not be complete yet. If group is None, the group was not found. |
get_group_results
async
¶
get_group_results(group_id: str) -> list[dict[str, Any]]
Get aggregated results/digests from a completed group's tasks.
cancel_group
async
¶
cancel_group(group_id: str, *, reason: str | None = None, propagate: bool = True) -> bool
Cancel a task group and optionally all its tasks.
apply_group_patches
async
¶
apply_group_patches(group_id: str, *, action: Literal['apply', 'reject'] = 'apply', strategy: MergeStrategy | None = None) -> bool
Apply or reject all pending patches for a task group.
set_turn_id
¶
set_turn_id(turn_id: str | None) -> None
Set the current foreground turn ID for group name resolution.
auto_seal_open_groups
async
¶
auto_seal_open_groups(turn_id: str | None = None) -> int
Auto-seal all OPEN groups created in the given turn (or current turn).
Called when foreground yields to ensure groups don't stay open. Returns count of groups sealed.
TaskResult
dataclass
¶
TaskResult(payload: Any | None = None, context_patch: ContextPatch | None = None, digest: list[str] = list(), artifacts: list[dict[str, Any]] = list(), sources: list[dict[str, Any]] = list(), notification: NotificationPayload | None = None, metadata: dict[str, Any] = dict())
Outcome of a task pipeline, returned by :class:TaskPipeline callables.
Attributes:
| Name | Type | Description |
|---|---|---|
payload |
Any | None
|
The task's primary output value, if any. |
context_patch |
ContextPatch | None
|
Optional patch to merge into the session context (see |
digest |
list[str]
|
Human-readable summary lines describing the result. |
artifacts |
list[dict[str, Any]]
|
Structured artifacts produced by the task (e.g. files, generated content). |
sources |
list[dict[str, Any]]
|
Structured source/citation references backing the result. |
notification |
NotificationPayload | None
|
Optional notification to surface to the user about this task's completion. |
metadata |
dict[str, Any]
|
Free-form metadata associated with the result. |
artifacts
class-attribute
instance-attribute
¶
artifacts: list[dict[str, Any]] = field(default_factory=list)
sources
class-attribute
instance-attribute
¶
sources: list[dict[str, Any]] = field(default_factory=list)
metadata
class-attribute
instance-attribute
¶
metadata: dict[str, Any] = field(default_factory=dict)
TaskRuntime
¶
TaskRuntime(*, session: StreamingSession, state: TaskState, steering: SteeringInbox, context_snapshot: TaskContextSnapshot)
Runtime helpers exposed to task pipelines.
emit_update
¶
emit_update(update_type: UpdateType, content: Any, *, step_index: int | None = None, total_steps: int | None = None) -> StateUpdate
Build a :class:StateUpdate and publish it on the owning session.
If update_type is PROGRESS and content is a dict, the task's
stored progress snapshot is also updated in the registry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
update_type
|
UpdateType
|
The kind of update being emitted (progress, result, etc.). |
required |
content
|
Any
|
The update payload; interpretation depends on |
required |
step_index
|
int | None
|
Optional 0-based index of the current step, for progress reporting. |
None
|
total_steps
|
int | None
|
Optional total number of steps, for progress reporting. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
The |
StateUpdate
|
class: |
notify
¶
notify(payload: NotificationPayload) -> None
Emit a notification update for this task.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
payload
|
NotificationPayload
|
The notification content (severity, title, body, actions) to publish. |
required |
transport
¶
Transport contracts for bidirectional session connectivity.
SessionConnection
¶
SessionConnection(session: StreamingSession, transport: Transport)
Wires a StreamingSession to a bidirectional transport.
Initialize the connection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
StreamingSession
|
The streaming session whose updates are forwarded and which receives steering events. |
required |
transport
|
Transport
|
The bidirectional transport to wire the session to. |
required |
Transport
¶
Bases: Protocol
Bidirectional wire contract between a StreamingSession and a client.
Implementations bridge StateUpdates flowing out to the client and
SteeringEvents flowing in from the client, over any concrete transport
(WebSocket, SSE + POST, in-process queues, etc.).
send
async
¶
send(update: StateUpdate) -> None
Send a state update to the client.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
update
|
StateUpdate
|
The state update to deliver. |
required |
receive
async
¶
receive() -> SteeringEvent | None
Wait for and return the next steering event from the client.
Returns:
| Type | Description |
|---|---|
SteeringEvent | None
|
The next |
SteeringEvent | None
|
more events will arrive. |
scheduler
¶
Scheduled job contracts and a lightweight scheduler loop.
JobScheduler
¶
JobScheduler(*, store: JobStore, spawn: Callable[[JobDefinition], Awaitable[str]])
Polls due jobs and triggers task creation through a callback.
tick
async
¶
tick() -> None
Run one scheduling pass: spawn all due jobs and advance recurring schedules.
For each job returned by JobStore.list_due, records a JobRunRecord, invokes
the spawn callback, and if the job repeats, computes and persists its next
run time.
JobSchedulerRunner
¶
JobSchedulerRunner(scheduler: JobScheduler, *, poll_interval_s: float = 5.0)
Background loop that ticks the scheduler on an interval.
JobDefinition
¶
Bases: BaseModel
A scheduled background job: what to run, for which session, and when.
job_id
class-attribute
instance-attribute
¶
job_id: str = Field(default_factory=lambda: secrets.token_hex(8), description='Unique identifier for this job.')
session_id
class-attribute
instance-attribute
¶
session_id: str = Field(description='Session this job belongs to.')
task_payload
class-attribute
instance-attribute
¶
task_payload: dict[str, Any] = Field(default_factory=dict, description='Payload passed to the spawn callback when the job fires.')
schedule
class-attribute
instance-attribute
¶
schedule: ScheduleConfig = Field(description='Recurrence rule controlling when the job is due.')
delivery_policy
class-attribute
instance-attribute
¶
delivery_policy: dict[str, Any] = Field(default_factory=dict, description='Policy controlling how results from this job are delivered.')
enabled
class-attribute
instance-attribute
¶
enabled: bool = Field(default=True, description='Whether the job is eligible to run; disabled jobs are skipped.')
created_at
class-attribute
instance-attribute
¶
created_at: datetime = Field(default_factory=_utc_now, description='When the job was created.')
updated_at
class-attribute
instance-attribute
¶
updated_at: datetime = Field(default_factory=_utc_now, description='When the job was last modified.')
ScheduleConfig
¶
Bases: BaseModel
Recurrence rule for a scheduled job.
A one-shot job sets only next_run_at; a recurring job also sets interval_s
so next_after can compute the following run time after each tick.
interval_s
class-attribute
instance-attribute
¶
interval_s: int | None = Field(default=None, description='Seconds between runs. None means the job does not repeat.')
next_run_at
class-attribute
instance-attribute
¶
next_run_at: datetime | None = Field(default=None, description='Next timestamp at which the job is due to run.')
timezone
class-attribute
instance-attribute
¶
timezone: str | None = Field(default=None, description='IANA timezone name used for interpreting schedule times, if any.')
next_after
¶
next_after(when: datetime) -> datetime | None
Compute the next run time after a given timestamp.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
when
|
datetime
|
The reference timestamp (typically the current run time) to offset from. |
required |
Returns:
| Type | Description |
|---|---|
datetime | None
|
The next run timestamp, or None if |
models
¶
Session/task models for bidirectional streaming and background work.
Most persistence-facing task/steering models live in penguiflow.state.models.
This module re-exports them for backward compatibility.
TaskContextSnapshot
¶
Bases: BaseModel
spawned_at
class-attribute
instance-attribute
¶
spawned_at: datetime = Field(default_factory=_utc_now)
llm_context
class-attribute
instance-attribute
¶
llm_context: dict[str, Any] = Field(default_factory=dict)
tool_context
class-attribute
instance-attribute
¶
tool_context: dict[str, Any] = Field(default_factory=dict)
artifacts
class-attribute
instance-attribute
¶
artifacts: list[dict[str, Any]] = Field(default_factory=list)
TaskStatus
¶
Bases: str, Enum
TaskType
¶
NotificationAction
¶
Bases: BaseModel
A single actionable button/option attached to a NotificationPayload.
id
class-attribute
instance-attribute
¶
id: str = Field(description='Stable identifier for this action, used when the user selects it.')
label
class-attribute
instance-attribute
¶
label: str = Field(description='Human-readable label shown to the user.')
payload
class-attribute
instance-attribute
¶
payload: dict[str, Any] = Field(default_factory=dict, description='Arbitrary data returned to the caller when this action is selected.')