Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 39 additions & 0 deletions changelog.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,45 @@ icon: rss
mode: center
---

<Update label="July 2026">
<Frame>
<img src="/assets/changelog/2026-07-workflow-deployment-rollback.gif" alt="Deploying a workflow release to a cluster and rolling the cluster back to an earlier release in the Tilebox Console" />
Comment thread
snamber marked this conversation as resolved.
</Frame>

## Workflow Management and Operations

Tilebox now exposes more workflow operations across the Console, SDKs, CLI, MCP server, and runner deployments. You can manage workflow releases and clusters from the Console, filter jobs by compute location, schedule automations in local time, and start release runners from an official Tilebox container image.

### What changed

- **Workflow management in the Console.** Create and edit workflows, inspect release history, tasks, runtime configuration, and artifacts, and deploy or undeploy releases across clusters. You can also delete workflows or unpublish individual releases without deleting existing jobs.
- **Redesigned cluster pages.** The Console now provides a clearer cluster overview and dedicated detail pages for deployed workflow releases and tasks. From a cluster page, you can edit the cluster, deploy another workflow or release version, or undeploy a release. Protected default clusters are clearly marked.
- **Job filtering by cluster.** Filter jobs by one or more cluster slugs in the Console, Python and Go SDKs, and CLI. This makes it easier to inspect work assigned to specific development, production, or specialized compute infrastructure.
- **Expanded MCP coverage.** AI agents using the Tilebox MCP server can manage clusters, workflows, releases, and jobs; inspect logs and spans; view automations; and query decoded dataset datapoints, including spatial queries.
- **Timezone-aware Cron schedules.** Cron automations now accept standard five-field expressions with lists, ranges, steps, named weekdays, and named months. Prefix a schedule with `CRON_TZ=<timezone>` to use an IANA timezone, or use helpers such as `@hourly`, `@daily`, `@weekly`, `@monthly`, and `@yearly`. Schedules without a timezone continue to use UTC.
- **Official runner image.** The release-runner image is available at `ghcr.io/tilebox/runner`. It includes the Tilebox CLI, `uv`, Python 3.12 through 3.14, Git, Git LFS, and common geospatial build dependencies. The image runs `tilebox runner start` by default and can be configured for a cluster through environment variables.

For example, this schedule runs at 09:00 on weekdays in Vienna and follows daylight saving time automatically:

```text
CRON_TZ=Europe/Vienna 0 9 * * 1-5
```

### Start here

<Columns cols={1}>
<Card title="Manage workflow deployments" icon="rocket" href="/workflows/build-and-deploy/cluster-deployments" horizontal>
Deploy workflow releases to clusters and control what release runners can execute.
</Card>
<Card title="Configure Cron triggers" icon="clock" href="/workflows/automations/cron" horizontal>
Define recurring jobs with standard Cron expressions, timezone prefixes, and schedule helpers.
</Card>
<Card title="Deploy to your compute" icon="server" href="/guides/workflows/deploy-to-your-compute" horizontal>
Run workflow releases on compute environments you control.
</Card>
</Columns>
</Update>

<Update label="June 2026">
<Frame>
<img src="/assets/changelog/2026-06-agentic-workflows-light.png" alt="Closed workflow iteration loop from deploy to run to observe to fix" className="dark:hidden" />
Expand Down
32 changes: 32 additions & 0 deletions workflows/concepts/tasks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ Tasks often require input parameters to operate. These inputs can range from sim
Tasks must be **serializable to JSON or to protobuf** because they may be distributed across a cluster of [runners](/workflows/concepts/runners).
</Info>

<Info>
Keep task inputs small. Task inputs are part of the workflow graph and are not intended for large manifests, file lists, arrays, or binary payloads. Store large data in object storage or the [job cache](/workflows/run-and-inspect/caches), then pass a compact reference such as a cache key, object prefix, scene ID, shard index, or time range.
</Info>

<Info>
In Go, task parameters must be exported fields of the task struct (starting with an uppercase letter), otherwise they will not be serialized to JSON.
</Info>
Expand Down Expand Up @@ -662,6 +666,34 @@ Tasks often rely on other tasks. For example, a task that processes data might d
The `depends_on` argument accepts a list of tasks, enabling a task to depend on multiple other tasks.
</Note>

### Dependency limit for subtasks

When a task finishes, Tilebox automatically groups its submitted subtasks by their dependencies. One task execution can create up to 64 groups. This limit applies to distinct sets of dependencies, not the number of subtasks: independent subtasks form one group, as do subtasks that all depend on the same tasks.

A workflow reaches the limit when one task creates many subtasks with different dependencies. Long chains and pairwise dependencies are common examples because every subtask depends on a different predecessor.

<CodeGroup>
```python Good: many tasks share one dependency shape
def execute(self, context: ExecutionContext):
# All map tasks are independent, so they form one submission group.
maps = context.submit_subtasks([MapItem(i) for i in range(200)])

# The reducer depends on the whole map group, so this adds one more group.
context.submit_subtask(ReduceItems(), depends_on=maps)
```

```python Avoid: each task has a different dependency shape
def execute(self, context: ExecutionContext):
previous = None
for i in range(70):
# Each task depends on a different previous task.
# This creates 70 submission groups and exceeds the limit.
previous = context.submit_subtask(Step(i), depends_on=previous)
```
</CodeGroup>

If one task would create more than 64 groups, split the submissions across multiple tasks so that each task creates fewer distinct dependency sets.

A workflow with dependencies might look like this:

<CodeGroup title="Task Composition">
Expand Down