Use Case 029: Task-Type Routing & Agent Provisioning
Overview
| Property |
Value |
| Use Case ID |
UC-029 |
| Use Case Name |
Task-Type Routing & Agent Provisioning |
| Module |
Agent Identity โ LLM Gateway |
| Priority |
High |
| Status |
๐ง Partially Implemented |
| Version |
1.0 |
| Last Updated |
June 15, 2026 |
Implementation status (agent-identity release, June 2026): partial. Shipping: the TaskType registry (CRUD at /ai-gateway/task-types), the dispatcher's classification-filtered resolution, and agent provisioning (agents carry AllowedTaskTypes + DefaultTaskType, set via the setup wizard / agent forms). Not yet built: the ordered model chain with a preference + health cascade (a task type currently routes to a single DefaultModelDeploymentId), the two distinct provisioning UX paths described below (purpose-picker / direct-model-picker), and seeded starter task types.
Description
This use case describes the TaskType registry โ the routing primitive of the Application Manager (AM) LLM Gateway โ and the two agent-provisioning UX paths that feed it. A TaskType binds a logical job (developer.code-generation, chat.general, analysis.financial) to an ordered modelChain of ModelDeployments, plus per-task defaults (responseSchema, timeout, maxRetries, temperature, classificationFloor). The dispatcher (UC-030) resolves a task type to the first viable deployment after a preference cascade and classification filter. Admins configure model selection once, per task type, and many agents share it โ so swapping the underlying model chain happens in one place.
This is part of the agent-identity release. The SDK master design is riptide-sdk/docs/plans/AGENT-IDENTITY-ARCHITECTURE.md; the AM-side plan is docs/internal/agent-identity-plan.md (ยง2 and ยง3.7). The gateway absorbs the RAF-SVC-LLM specification โ its task-type routing and deployment cascade become AM's design. Crucially, AM is task-types-only at the data layer: both provisioning UX paths โ the purpose-picker and the direct-model-picker โ produce the same TaskType data, so the dispatcher, dashboards, and audit see one mechanism with no special-case code. An agent's AllowedTaskTypes + DefaultTaskType replace the older AllowedProviderModels concept.
Implementation note โ guided setup. The shipped entry point for standing up this chain is the AI Gateway โ Setup wizard (/ai-gateway/setup). It walks provider account โ model โ deployment โ task type โ agent in order and shows a live readiness banner that reports real callability (a task type is callable only when it's enabled, wired to an enabled deployment whose model exists and whose provider account is enabled with a resolvable key โ the same guards the dispatcher applies). It lists the specific blocker when a step isn't ready, and an on-demand Run live check issues a real provider probe. See AI Gateway & Model Governance.
Actors
| Actor |
Description |
Role |
| Provisioning Admin / Steward |
Holds llm.gateway.config and agents.write; registers task types and provisions agents |
Primary |
| AM LLM Gateway |
Hosts the TaskType registry and the ResolveTaskType resolver |
Supporting |
| AI Agent |
Non-human identity whose AllowedTaskTypes/DefaultTaskType are set during provisioning; later issues dispatch requests |
Primary |
| LLM Providers |
Backing providers reached through the resolved ModelDeployments |
External |
| AuditLog |
Records task-type registration/edits and agent provisioning with actor chain |
Supporting |
Preconditions
- Application Manager is running; the agent-identity EF migration (creating the
TaskType table in IdentityDbContext and seeding starter task types) has been applied.
- At least one
ProviderAccount and one ModelDeployment exist (UC-028).
- The acting principal is authenticated (
X-Api-Key or admin cookie) and holds llm.gateway.config (for task types) and/or agents.write (for provisioning).
- The agent being provisioned exists or is being created in the same flow (UC-025).
- Starter task types are seeded; on first
ProviderAccount registration the admin is prompted to bind them to available deployments.
Postconditions
Success Postconditions
- A
TaskType is persisted with its component-namespaced id ({component}.{task-name}), ordered modelChain, and defaults.
- An agent has
AllowedTaskTypes set and a DefaultTaskType chosen, via either provisioning path.
ResolveTaskType returns an ordered list of viable ModelDeployments after the preference cascade and classification filter.
- Starter task types are bound to real deployments, so dispatch has a working chain from day one.
- Registration/provisioning events are written to
AuditLog.
Failure Postconditions
- A
TaskType whose modelChain references no viable deployment (all unreachable or below classificationFloor) is rejected or flagged unroutable.
- A
classificationFloor exceeding every chain deployment's maxClassification is rejected.
- An agent provisioned with no resolvable task type cannot dispatch โ UC-030 fails closed.
- Duplicate task-type ids are rejected.
Primary Flow Sequence
sequenceDiagram
actor Admin as Provisioning Admin
participant Web as TaskTypesController / AgentsController
participant Med as MediatR
participant Resolve as ResolveTaskType
participant Repo as LlmGateway Repos
participant Audit as AuditLog
Admin->>Web: Register task type (id, modelChain, defaults)
Web->>Med: RegisterTaskType command
Med->>Repo: Validate deployments exist + classificationFloor satisfiable
Repo-->>Med: Validation OK
Med->>Repo: Persist TaskType
Med->>Audit: Write registration entry
Med-->>Web: Task type registered
Admin->>Web: Provision agent (purpose-picker: select task types)
Web->>Med: Set AllowedTaskTypes + DefaultTaskType
Med->>Resolve: ResolveTaskType(DefaultTaskType)
Resolve->>Repo: Apply cascade + classification filter
Repo-->>Resolve: Ordered viable deployments
Resolve-->>Med: At least one viable deployment
Med->>Audit: Write provisioning entry
Med-->>Web: Agent provisioned
Web-->>Admin: Agent ready to dispatch
UC-029a: Register / Edit a Task Type & Model Chain
Triggers
- Admin opens LLM Gateway > Task Types > New (or edits one) and submits, or
POST /api/llm/task-types / PUT /api/llm/task-types/{taskType}.
Basic Flow
- Admin enters a component-namespaced
taskType id ({component}.{task-name}, e.g. analysis.financial) and a description.
- Admin orders a
modelChain โ a list of ModelDeployments tried in preference order at dispatch.
- Admin sets defaults: optional
responseSchema (for structured output), timeout, maxRetries, optional temperature, optional classificationFloor.
RegisterTaskType validates the chain references existing deployments and that at least one chain deployment's maxClassification meets the classificationFloor.
- The
TaskType is persisted; the registration is audited.
UpdateTaskType edits the chain or defaults in place โ every agent referencing the task type immediately picks up the new chain (the one-place-to-swap property).
Alternative Flows
- A1:
classificationFloor unsatisfiable โ no chain deployment's maxClassification reaches the floor; rejected with a validation error.
- A2: Empty / all-unreachable chain โ task type flagged unroutable; agents may still reference it but dispatch fails closed until a viable deployment is added.
- A3: Duplicate id โ
taskType already registered; rejected.
- A4: Private direct-picker task type edited by hand โ
agent.{agentName}.direct task types are owned by the direct-picker flow; manual edits are allowed but warned (they may be overwritten on re-provisioning).
UC-029b: Resolve Task Type to Deployment (Cascade + Classification Filter)
Triggers
- The dispatcher (UC-030) calls
ResolveTaskType(taskType, requestClassification); or an admin previews resolution from the task-type editor.
Basic Flow
ResolveTaskType loads the task type and its modelChain.
- It applies the preference cascade: walk the chain in order, keeping deployments that are not
Unreachable.
- It applies the classification filter: drop any deployment whose
maxClassification is below the request's data classification (or the task's classificationFloor).
- The result is an ordered list of viable
ModelDeployments โ the first is the primary, the rest are fallbacks for retry/model-chain fallback (UC-030).
- If the list is non-empty, resolution succeeds; the dispatcher proceeds.
Alternative Flows
- A1: No viable deployment โ every chain entry is unreachable or below classification; resolution returns empty and dispatch fails closed (
Unroutable).
- A2: Health-degraded primary โ a
Degraded primary is kept but ranked after Healthy peers where the cascade allows.
- A3: Classification floor stricter than request โ the task's
classificationFloor is applied even when the request classification is lower, raising the effective filter.
sequenceDiagram
participant Disp as LlmDispatchService
participant Resolve as ResolveTaskType
participant TT as TaskType Repo
participant Dep as ModelDeployment Repo
Disp->>Resolve: ResolveTaskType(taskType, requestClassification)
Resolve->>TT: Load task type + modelChain
TT-->>Resolve: Ordered chain + classificationFloor
Resolve->>Dep: Fetch deployments in chain
Dep-->>Resolve: Deployments (health, maxClassification)
Resolve->>Resolve: Cascade (drop Unreachable, prefer Healthy)
Resolve->>Resolve: Classification filter (>= max(reqClass, floor))
alt Viable deployments remain
Resolve-->>Disp: Ordered viable deployments
else None viable
Resolve-->>Disp: Empty (Unroutable, fail closed)
end
UC-029c: Purpose-Picker Agent Provisioning
Triggers
- Admin provisions an agent via "What will this agent do?" in the agent provisioning UI.
Basic Flow
- The flow lists available task types (
developer.code-generation, chat.general, analysis.financial, โฆ) with descriptions.
- Admin selects one or several task types.
- AM sets the agent's
AllowedTaskTypes to the selected set.
DefaultTaskType is set to the first selected task type.
- No new task type is created โ the agent references shared, admin-managed task types.
- This is the strategic path: many agents share a task type, so swapping the underlying model chain happens once in the registry (UC-029a) and propagates to all of them.
Alternative Flows
- A1: Selected task type unroutable โ admin warned at provisioning time that the task type currently resolves to no viable deployment; provisioning may proceed but dispatch will fail closed until fixed.
- A2: Zero selections โ provisioning blocked; an agent must have at least one allowed task type.
UC-029d: Direct-Model-Picker Agent Provisioning
Triggers
- Admin provisions an agent via "Which models can this agent use?" in the agent provisioning UI.
Basic Flow
- The flow lists available
ModelDeployments (model, provider, classification, health) instead of task types.
- Admin picks one or several deployments, in preference order.
- AM creates a private task type named
agent.{agentName}.direct with the picked deployments as its modelChain.
- AM sets that private task type as both the agent's
AllowedTaskTypes and its DefaultTaskType.
- The admin never types the words "task type" โ the mechanism is hidden behind a model picker.
- This is the simple path for one-off agents; the produced data is identical to the purpose-picker output, so the dispatcher and audit see one mechanism.
Alternative Flows
- A1: Re-provision with a different model set โ the existing
agent.{agentName}.direct chain is replaced; an audit entry records the change.
- A2: Picked deployment later disabled โ the private chain still references it; resolution (UC-029b) filters it out and falls through to the next picked deployment.
- A3: Name collision โ if
agent.{agentName}.direct already exists for a different agent, AM disambiguates with the agent id.
UC-029e: Seed & Bind Starter Task Types
Triggers
- Initial agent-identity migration runs (seeds starter task types); first
ProviderAccount registration prompts the admin to bind them.
Basic Flow
- The initial migration seeds starter task types:
developer.code-generation, developer.code-explanation, developer.code-review, chat.general, chat.customer-support, analysis.financial, analysis.legal, summarization.document, embedding.search.
- Default chains reference common cloud-provider deployments by intent (not yet bound to a specific account).
- When an admin registers their first
ProviderAccount and its deployments (UC-028), AM prompts: "Bind starter task types to your available deployments?"
- The admin maps each starter task type's chain to one or more real
ModelDeployments.
UpdateTaskType persists the bound chains; the starter task types become routable.
- Agents provisioned via the purpose-picker can immediately select these starter types.
Alternative Flows
- A1: Admin skips binding โ starter task types remain unroutable until bound; dispatch against them fails closed.
- A2: Partial binding โ only some starter types are bound; the rest stay unroutable without blocking the bound ones.
- A3: Embedding task type โ
embedding.search binds only to embedding-capable deployments; non-embedding deployments are not offered for it.
API Endpoints
| Method |
Path |
Auth |
Purpose |
| POST |
/api/llm/task-types |
X-Api-Key + llm.gateway.config |
Register a task type |
| PUT |
/api/llm/task-types/{taskType} |
X-Api-Key + llm.gateway.config |
Update a task type / model chain |
| GET |
/api/llm/task-types |
X-Api-Key + llm.gateway.read |
List task types (registry view) |
| GET |
/api/llm/task-types/{taskType}/resolve |
X-Api-Key + llm.gateway.read |
Resolve a task type to ordered viable deployments |
| POST |
/api/agents/{id}/provision/purpose |
X-Api-Key + agents.write |
Purpose-picker provisioning (select task types) |
| POST |
/api/agents/{id}/provision/direct |
X-Api-Key + agents.write |
Direct-model-picker provisioning (select deployments) |
// POST /api/agents/{id}/provision/purpose
// Request
{
"selectedTaskTypes": [
"developer.code-generation",
"developer.code-review"
]
}
// Response 200
{
"agentId": "01J8ZA10AGENT00000000001",
"allowedTaskTypes": [
"developer.code-generation",
"developer.code-review"
],
"defaultTaskType": "developer.code-generation",
"provisioningPath": "PurposePicker",
"defaultTaskTypeRoutable": true
}
Business Rules
| Rule |
Description |
| BR-1 |
Task-type ids are component-namespaced {component}.{task-name}; ids are unique |
| BR-2 |
A TaskType carries an ordered modelChain, optional responseSchema, timeout, maxRetries, optional temperature, optional classificationFloor |
| BR-3 |
Editing a task type's modelChain propagates to every agent referencing it (one place to swap) |
| BR-4 |
ResolveTaskType applies the preference cascade (drop Unreachable) then the classification filter (>= max(requestClassification, classificationFloor)) |
| BR-5 |
No viable deployment after resolution is Unroutable and dispatch fails closed |
| BR-6 |
Both provisioning paths produce TaskType data; the dispatcher, dashboards, and audit see one mechanism |
| BR-7 |
Purpose-picker sets AllowedTaskTypes to the selection and DefaultTaskType to the first selected |
| BR-8 |
Direct-model-picker creates a private agent.{agentName}.direct task type and sets it as both AllowedTaskTypes and DefaultTaskType |
| BR-9 |
An agent must have at least one allowed task type; zero selections is blocked |
| BR-10 |
Starter task types are seeded in the initial migration and bound to real deployments at first ProviderAccount registration |
| BR-11 |
AllowedTaskTypes + DefaultTaskType replace the older AllowedProviderModels concept |
Data Requirements
TaskType
| Field |
Type |
Constraints |
| TaskType |
string |
Primary key; component-namespaced {component}.{task-name}; unique |
| Description |
string |
Max 1000 chars |
| ModelChain |
ordered list of Guid |
Each references a ModelDeployment; preference order |
| ResponseSchema |
string? (JSON Schema) |
Optional; enables structured-output enforcement |
| Timeout |
int (ms/s) |
> 0 |
| MaxRetries |
int |
โฅ 0 |
| Temperature |
decimal? |
Optional; provider-clamped range |
| ClassificationFloor |
enum? |
Optional minimum classification the task requires |
| IsPrivate |
bool |
True for agent.{agentName}.direct direct-picker task types |
Agent provisioning fields (on AgentIdentity โ see UC-025)
| Field |
Type |
Constraints |
| AllowedTaskTypes |
set of string |
Each references a TaskType; non-empty |
| DefaultTaskType |
string |
Must be in AllowedTaskTypes |
| ProvisioningPath |
enum |
PurposePicker or DirectModelPicker (reporting only) |
Security Considerations
- Authentication: API routes require
X-Api-Key; Web admin routes require the admin cookie.
- Authorization / capabilities: task-type registry writes gated by
llm.gateway.config; agent provisioning gated by agents.write; reads by llm.gateway.read. Capabilities compose into roles via the existing RBAC model.
- Data protection: task types and chains carry no secrets; provider credentials stay on
ProviderAccount (UC-028) and are never referenced in task-type data.
- Audit: task-type registration/edits and both provisioning paths write
AuditLog entries with actor chain. Direct-picker chain replacement is audited so the swap is forensically visible.
- PII handling: task-type and provisioning data carry no end-user PII;
classificationFloor is the lever that keeps high-classification work off low-classification deployments โ enforced at resolution and again at dispatch (UC-030).
Testing Scenarios
| ID |
Scenario |
Expected Result |
| T-1 |
Register a task type with a valid ordered chain |
Persisted; routable; registration audited |
| T-2 |
Register with classificationFloor no chain deployment satisfies |
Rejected with validation error |
| T-3 |
Register with an empty / all-unreachable chain |
Flagged Unroutable; agents may reference but dispatch fails closed |
| T-4 |
Register a duplicate task-type id |
Rejected |
| T-5 |
Edit a shared task type's chain |
All referencing agents pick up the new chain immediately |
| T-6 |
ResolveTaskType with all-healthy chain |
Ordered viable deployments returned, primary first |
| T-7 |
ResolveTaskType with Unreachable primary |
Primary dropped; next chain entry returned as primary |
| T-8 |
ResolveTaskType where every entry is below classification |
Empty result; Unroutable; dispatch fails closed |
| T-9 |
ResolveTaskType with Degraded primary |
Primary kept but ranked after Healthy peers |
| T-10 |
classificationFloor stricter than request classification |
Effective filter raised to the floor |
| T-11 |
Purpose-picker: select two task types |
AllowedTaskTypes = both; DefaultTaskType = first selected |
| T-12 |
Purpose-picker: zero selections |
Provisioning blocked |
| T-13 |
Purpose-picker: select an unroutable task type |
Admin warned; provisioning may proceed; dispatch fails closed until fixed |
| T-14 |
Direct-picker: select two deployments |
Private agent.{agentName}.direct task type created with both as chain; set as AllowedTaskTypes + DefaultTaskType |
| T-15 |
Direct-picker: re-provision with different deployments |
Private chain replaced; change audited |
| T-16 |
Direct-picker: picked deployment later disabled |
Resolution filters it out; falls through to next picked deployment |
| T-17 |
Both paths produce identical task-type data shape |
Dispatcher and audit see one mechanism; no special-case branch |
| T-18 |
Initial migration seeds starter task types |
All nine starter types present |
| T-19 |
First ProviderAccount registration prompts binding |
Admin prompted; bound chains become routable |
| T-20 |
Admin skips starter binding |
Starter types remain unroutable; dispatch against them fails closed |
| T-21 |
embedding.search offered only embedding-capable deployments |
Non-embedding deployments not offered for binding |
| T-22 |
Caller lacks llm.gateway.config registering a task type |
403; no change |
| T-23 |
Caller lacks agents.write provisioning an agent |
403; no change |
| T-24 |
DefaultTaskType set outside AllowedTaskTypes |
Rejected by validation |
| T-25 |
Agent with no resolvable task type issues a dispatch |
UC-030 fails closed (Unroutable) |
- UC-025: Agent Identity Registration & Lifecycle โ the agent that carries
AllowedTaskTypes/DefaultTaskType.
- UC-028: LLM Provider Account & Deployment Management โ the deployments task-type chains resolve to.
- UC-030: LLM Request Dispatch โ consumes
ResolveTaskType output as the first dispatch step.
Revision History
| Version |
Date |
Author |
Notes |
| 1.0 |
June 9, 2026 |
Platform Architecture Team |
Initial draft |