Define a task
This guide describes best practices for authoring custom task definitions for use in Lattice. Custom task definitions allow you to extend Lattice’s tasking capabilities with your own specialized workflows.
Before you begin
- Familiarize yourself with tasks in Lattice.
- To create tasks, set up your Lattice environment.
- Review the Protobuf files and packages guide to understand Protobuf fundamentals.
Authoring tasks
A custom task is a Protobuf message type that contains the information your asset requires to execute a task autonomously. The complexity of your task definition depends on your integration’s requirements. For example:
- Simple tasks: A sensor may define an on/off toggle message
- Entity-targeted tasks: A tracking system may define a message containing an
entity_idto track - Complex tasks: An autonomous vehicle may define multiple parameters including waypoints, speed limits, sensor configurations, and priority levels
Custom tasks give you the flexibility to model domain-specific workflows while maintaining type safety and compatibility across your Lattice deployment.
At its simplest, a task definition is a single Protobuf message. For example, the following schema defines a task that turns a sensor on:
Next, you’ll learn how to organize definitions into packages, how Lattice identifies them, and how to model richer task parameters.
Create a package
Define your tasks as Protobuf messages as part of a package. A package should contain all relevant message types to compose tasks that express an integration’s capabilities. Naming your package clearly and precisely is crucial to avoid potential naming conflicts.
Use a consistent package naming pattern: org.repository.package.version
Where:
- org: Your organization name in the Schema Registry.
- repository: Your repository name in the Schema Registry.
- package: A descriptive name for your task domain, for example,
reconnaissance,navigation, orsensor. - version: The API version, for example,
v1,v2v1alphaorv2test.
During early development, mark your package as unstable by appending a stability marker (alpha, beta, or test) to the version.
The Schema Registry enforces breaking change detection on all packages, regardless of the stability marker. If you need to make a breaking change, you must create a new version.
Fully qualified names
The fully qualified name of a message consists of its package and message name:
The above message yields the name: org.example.reconnaissance.v1beta.Objective.
All protobuf type URLs are prefixed with type.googleapis.com. You will always reference your task definition
by its type URL, for example: type.googleapis.com/org.example.reconnaissance.v1beta.Objective.
Globally unique names
Each fully qualified message name must be globally unique within the Schema Registry. This prevents naming conflicts when multiple organizations publish schemas.
This type URL is also how you advertise a task on an asset. The Entity model’s
taskCatalog lists the tasks an
asset can perform, and each entry’s taskSpecificationUrl is the type URL of a task definition:
An operator can only assign a task to an asset if the asset’s taskCatalog advertises that task’s
type URL. To learn how to publish an asset with a taskCatalog and process the tasks it receives,
see Integrate an agent.
For more information about Protobuf packages and naming, see Protobuf files and packages in the Buf documentation.
Breaking change protection
The Schema Registry enforces breaking change detection for all packages. This ensures backward compatibility for consumers of your schemas. You can deprecate old fields, or if necessary, release a new version of your package.
For a complete guide on breaking changes, see the Buf breaking change detector documentation.
Define a custom schema
Every task in Lattice is represented by the Task message. Its specification field is a
google.protobuf.Any, which lets
Lattice carry any custom task type without knowing its schema in advance:
Lattice packs the message you define into this specification field when a task is created. To author an example custom task, create a new
.proto file. For example:
Best practices
- Use descriptive comments: Document each field and enum value to help other developers understand your schema.
- Use wrapper types: For optional numeric fields, use
google.protobuf.*Valuewrapper types instead of primitive types. - Start with stability markers: Use
v1alphaorv1betaduring development to allow breaking changes. - Reserved field 0: Always reserve enum value
0for anINVALIDorUNSPECIFIEDvariant. In proto3, an unset enum field defaults to0, so reserving it keeps an intentional value from being indistinguishable from an unset one.
Common patterns
Track entity
Mission parameters
What’s next?
- Publish your schema to make it available for use.
- Use your task definition to create tasks in Lattice.
- Configure your agents to listen for tasks assigned to them.