Restrict which workers a task can be assigned to based on required capabilities
Capabilities per Task and Worker
Capability matching lets you require that a task only be assigned to a worker whose vehicle can actually meet its needs. For example, a task requiring refrigeration should only go to a worker with a refrigerated vehicle. Route Optimization enforces this as a hard constraint: a task with an unmet capability requirement will never be assigned to an incompatible worker.
Capabilities are set via the opt_compat_attributes metadata key, which can be attached to both Tasks and Workers. This field is fully optional. Omitting it preserves current behavior.
ROv3 Requirement
Capability matching is only available on Route Optimization v3 (ROv3) and isn't supported on the legacy optimizer. If you're not sure which version your organization is running, contact Onfleet support or your Customer Success Manager before relying on this.
Setting Capabilities via Metadata
opt_compat_attributes is a standard metadata entry, not a dedicated task/worker field. It follows the same rules as any other metadata property. If you haven't worked with metadata before, read Working with metadata first. The essentials for this field are:
- The name must be exactly
opt_compat_attributes. Route Optimization only reads capabilities from a metadata entry with this specific name. Any other name is just ordinary metadata and has no effect on assignment. typemust be"array", and array entries require asubtype. For a list of capability strings, that's"subtype": "string".- Metadata is set via the
metadataarray on task creation, or viaPUTon an existing task or worker. A plainPUTwith ametadataarray replaces the entire array, so if the entity already has other metadata you want to keep, include those entries too, or use the$setcommand to update just this one property without touching the rest. - Capability matching on
opt_compat_attributesis case sensitive (see below). That's a property of how Route Optimization reads this value, not something metadata itself enforces. Metadata has no built in case normalization for any field.
| Name | Set On | Type | Description |
|---|---|---|---|
opt_compat_attributes | Task metadata | array of strings | Optional. The capabilities this task requires (e.g. ["refrigeration"]). A worker must possess every capability listed here to be eligible for assignment. |
opt_compat_attributes | Worker metadata | array of strings | Optional. The capabilities this worker's vehicle provides (e.g. ["refrigeration", "fragile"]). Can be a superset of any single task's requirements. |
How Matching WorksMatching is a superset check. A task requiring ["refrigeration"] can be assigned to a worker with ["refrigeration"], ["refrigeration", "fragile"], or any other set that contains at least refrigeration. The worker's capabilities don't need to match exactly, they just need to cover everything the task requires.
Matching is case sensitive. "Refrigeration" and "refrigeration" are treated as different capabilities, so keep casing consistent across your tasks and workers.
A task with no
opt_compat_attributeshas nothing to match against, so it's treated as a common assignment. It can be assigned to any worker, regardless of what capabilities that worker has, the same as if capabilities weren't in use at all.
Matching is a superset check. A task requiring ["refrigeration"] can be assigned to a worker with ["refrigeration"], ["refrigeration", "fragile"], or any other set that contains at least refrigeration. The worker's capabilities don't need to match exactly, they just need to cover everything the task requires.
Matching is case sensitive. "Refrigeration" and "refrigeration" are treated as different capabilities, so keep casing consistent across your tasks and workers.
A task with no opt_compat_attributes has nothing to match against, so it's treated as a common assignment. It can be assigned to any worker, regardless of what capabilities that worker has, the same as if capabilities weren't in use at all.
When No Worker QualifiesIf a task requires a capability that no worker in the optimization has, the task is not assigned. It appears in the
unassigned[]array of the optimization response with reason code300.
Example Request, creating a task with a capability requirement:
curl -X POST "https://onfleet.com/api/v2/tasks" \
-u "<your_onfleet_api_key>:" \
-d '{"destination": {
"address": {"unparsed": "166 Chacabuco, Buenos Aires"}
},
"metadata": [
{
"name": "opt_compat_attributes",
"type": "array",
"subtype": "string",
"value": ["refrigeration"]
}
]}'
Example Request, setting the matching capability on a worker:
curl -X PUT "https://onfleet.com/api/v2/workers/<workerId>" \
-u "<your_onfleet_api_key>:" \
-d '{"metadata": [
{
"name": "opt_compat_attributes",
"type": "array",
"subtype": "string",
"value": ["refrigeration"]
}
]}'
Behavior by Optimization Mode
Capability matching behaves differently depending on which Route Optimization mode is used, since only some modes have a concrete worker/vehicle instance to source capabilities from.
| Mode | Behavior |
|---|---|
| DRIVERS | Worker capabilities are read from opt_compat_attributes on each worker and passed through as the vehicle's capabilities. Matching is enforced normally. |
| SERVICE_AREA | Worker capabilities flow through the same way as DRIVERS mode. Matching is enforced normally. |
| VEHICLES | No capabilities are injected. There's no worker instance to source opt_compat_attributes from. Behavior is unchanged from today: capability requirements on a task have no effect in this mode. |
A Note on Walking WorkersCapability matching doesn't check whether a capability makes physical sense for a worker's vehicle type. A pedestrian worker with a
refrigerationcapability set in metadata (say, if they're carrying a cooler) is treated the same as any other qualifying worker. Onfleet doesn't restrict which capabilities can be assigned to which vehicle types.
Backward Compatibility
Tasks and workers that don't have opt_compat_attributes set are completely unaffected. No capabilities data is added to the optimization request, and optimization behavior is identical to today.
Live Values on Re-optimization
Capabilities are read live from the current task and worker records at the time an optimization runs. If you update a task's or worker's opt_compat_attributes and then re-optimize, the updated values are what gets used, not whatever was in effect during a prior run.
