task API
Table of Contents
upsquad/task/v1/task.proto
CreateTaskRequest
CreateTaskRequest creates a new Task in the pending state.
| Field | Type | Label | Description |
|---|---|---|---|
| requester_member_id | string | requester_member_id is the member who asked for the work (required). | |
| title | string | title is a short human-readable label (required). | |
| intent | string | intent is an optional machine-readable category for the request. | |
| payload_ref | string | payload_ref is an optional opaque pointer to the request payload. |
CreateTaskResponse
CreateTaskResponse returns the created Task.
| Field | Type | Label | Description |
|---|---|---|---|
| task | Task | task is the newly created Task. |
GetTaskRequest
GetTaskRequest retrieves a Task by id.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | id is the Task UUID (required). |
GetTaskResponse
GetTaskResponse returns the requested Task.
| Field | Type | Label | Description |
|---|---|---|---|
| task | Task | task is the requested Task. |
ListTasksRequest
ListTasksRequest lists Tasks for the caller's organisation.
| Field | Type | Label | Description |
|---|---|---|---|
| status_filter | TaskStatus | status_filter, when set to a value other than TASK_STATUS_UNSPECIFIED, restricts results to that status. | |
| requester_member_id | string | requester_member_id, when non-empty, restricts results to Tasks requested by that member. | |
| page | int32 | page is the 1-based page number. Defaults to 1. | |
| page_size | int32 | page_size is the maximum number of results per page. Max 100, default 20. |
ListTasksResponse
ListTasksResponse returns a paginated list of Tasks, newest first.
| Field | Type | Label | Description |
|---|---|---|---|
| tasks | Task | repeated | tasks is the page of Task records. |
| total_count | int32 | total_count is the total number of matching Tasks (for pagination). |
Task
Task is the per-instance unit of work and its accounting rollup.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | id is the Task UUID. | |
| org_id | string | org_id is the tenant organisation UUID (RLS scope). | |
| requester_member_id | string | requester_member_id is the member (human or agent) who asked for the work. References members.id. | |
| title | string | title is a short human-readable label for the Task. | |
| intent | string | intent is a machine-readable category / verb for the request (e.g. "draft_email", "triage_incident"). Empty until classified. | |
| payload_ref | string | payload_ref is an opaque pointer to the request payload (e.g. a Quad thread id or blob ref). The Task does not inline the payload. | |
| status | TaskStatus | status is the current lifecycle state. | |
| failure_reason | string | failure_reason explains a FAILED or REJECTED terminal state. Empty in all non-failure states. | |
| routed_team_id | string | routed_team_id is the team the Task was routed to. Empty until routed. | |
| workflow_run_ids | string | repeated | workflow_run_ids are the workflow runs spawned to execute this Task. The cost / elapsed rollup aggregates over these runs. |
| session_ids | string | repeated | session_ids are the agent sessions spawned to execute this Task. The token rollup aggregates llm_usage_events over these sessions. |
| cost_usd | double | cost_usd is the rolled-up cost across every linked workflow run (which in turn rolls up its actions — #1127). | |
| elapsed_ms | int64 | elapsed_ms is the rolled-up wall-clock effort across linked runs' actions. | |
| tokens | int64 | tokens is the rolled-up LLM token count (input + output) across linked sessions, sourced from the same llm_usage_events that BillingService meters. | |
| created_at | google.protobuf.Timestamp | created_at is when the Task was created. | |
| updated_at | google.protobuf.Timestamp | updated_at is when the Task last changed. |
TaskStatus
TaskStatus is the Task lifecycle state machine. Failure and rejection are first-class terminal states distinct from cancellation: FAILED is an execution error, REJECTED is a governance/approval denial, CANCELLED is an operator/requester abort.
| Name | Number | Description |
|---|---|---|
| TASK_STATUS_UNSPECIFIED | 0 | TASK_STATUS_UNSPECIFIED is the zero value; never persisted. |
| TASK_STATUS_PENDING | 1 | TASK_STATUS_PENDING — created, not yet routed to a team. |
| TASK_STATUS_ROUTED | 2 | TASK_STATUS_ROUTED — assigned to a team, not yet executing. |
| TASK_STATUS_RUNNING | 3 | TASK_STATUS_RUNNING — a delegate (agent or workflow) is executing. |
| TASK_STATUS_PAUSED_APPROVAL | 4 | TASK_STATUS_PAUSED_APPROVAL — blocked on a human approval gate. |
| TASK_STATUS_COMPLETED | 5 | TASK_STATUS_COMPLETED — finished successfully (terminal). |
| TASK_STATUS_FAILED | 6 | TASK_STATUS_FAILED — execution error; failure_reason set (terminal). |
| TASK_STATUS_REJECTED | 7 | TASK_STATUS_REJECTED — denied at a governance/approval gate; failure_reason carries the denial reason (terminal). |
| TASK_STATUS_CANCELLED | 8 | TASK_STATUS_CANCELLED — aborted by operator/requester (terminal). |
TaskService
TaskService is the external (Connect / gRPC) surface for the Task spine. It exposes creation and read paths only; the internal status-transition path is an in-process store interface consumed by the Coordinator (B1 #1227), not an RPC. All operations are tenant-scoped via JWT-derived scope claims and PostgreSQL row-level security.
Self-scoping rule (PRD §3.2 self-only invariant applied to tasks; MVP flow "ANY human asks Quad → Task created"): tasks.create / tasks.view are granted to EVERY built-in role including Member, but a caller whose grant is member-scoped (the built-in Member role shape) operates on their OWN tasks only — CreateTask requires requester_member_id == the caller (PERMISSION_DENIED otherwise), ListTasks is forced to requester == caller, and GetTask on another member's task is NOT_FOUND. A tenant-global grant (Owner/Admin/...) lifts the restriction.
| Method Name | Request Type | Response Type | Description |
|---|---|---|---|
| CreateTask | CreateTaskRequest | CreateTaskResponse | CreateTask records a new unit of work in the pending state. The requester is taken from the request; org scope comes from the ambient JWT claims (never from the request body). Callers without a tenant-global tasks.create grant may only name themselves as requester_member_id (self-scoped — PERMISSION_DENIED otherwise). |
| GetTask | GetTaskRequest | GetTaskResponse | GetTask retrieves a single Task by id within the caller's tenant. Callers without a tenant-global tasks.view grant can retrieve only tasks they requested; another member's task reads as NOT_FOUND. |
| ListTasks | ListTasksRequest | ListTasksResponse | ListTasks lists Tasks for the caller's organisation, newest first, optionally filtered by status and/or requester. Always paginated. Callers without a tenant-global tasks.view grant see only their own tasks: the requester filter is forced to the caller, and explicitly filtering on a different requester is PERMISSION_DENIED. |
Scalar Value Types
| .proto Type | Notes | C++ | Java | Python | Go | C# | PHP | Ruby |
|---|---|---|---|---|---|---|---|---|
| double | double | double | float | float64 | double | float | Float | |
| float | float | float | float | float32 | float | float | Float | |
| int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
| int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long | int64 | long | integer/string | Bignum |
| uint32 | Uses variable-length encoding. | uint32 | int | int/long | uint32 | uint | integer | Bignum or Fixnum (as required) |
| uint64 | Uses variable-length encoding. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum or Fixnum (as required) |
| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long | int64 | long | integer/string | Bignum |
| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int | uint32 | uint | integer | Bignum or Fixnum (as required) |
| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum |
| sfixed32 | Always four bytes. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
| sfixed64 | Always eight bytes. | int64 | long | int/long | int64 | long | integer/string | Bignum |
| bool | bool | boolean | boolean | bool | bool | boolean | TrueClass/FalseClass | |
| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode | string | string | string | String (UTF-8) |
| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str | []byte | ByteString | string | String (ASCII-8BIT) |