Skip to content
Closed
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
133 changes: 133 additions & 0 deletions examples/06-task-dependencies/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# 06 β€” Task Dependencies

A three-stage pipeline that chains Tasks with `dependsOn`. Each stage waits
for the previous one to succeed before starting, and downstream prompts
reference upstream outputs using Go template syntax.

## Use Case

Break a feature into sequential stages β€” implement, test, review β€” where
each agent builds on the previous agent's work on the same branch.

## Pipeline

```
implement ──> write-tests ──> review
```

1. **implement** β€” scaffolds the feature and pushes to a branch.
2. **write-tests** β€” waits for `implement`, then adds tests on the same branch.
3. **review** β€” waits for `write-tests`, then opens and reviews a PR.

## Resources

| File | Kind | Purpose |
|------|------|---------|
| `github-token-secret.yaml` | Secret | GitHub token for cloning and PR creation |
| `credentials-secret.yaml` | Secret | Claude OAuth token for the agent |
| `workspace.yaml` | Workspace | Git repository to clone |
| `tasks.yaml` | Task (x3) | The three-stage pipeline |

## How Dependencies Work

- A Task with `dependsOn: [other-task]` stays in `Waiting` phase until
every listed dependency reaches `Succeeded`.
- If any dependency fails, the dependent Task fails immediately.
- Downstream prompts can reference upstream outputs with Go `text/template`
syntax:

| Template Expression | Resolves To |
|---------------------|-------------|
| `{{ index .Deps "implement" "Outputs" }}` | Raw output lines from `implement` |
| `{{ index .Deps "implement" "Results" "branch" }}` | The `branch` result value |
| `{{ index .Deps "implement" "Results" "pr" }}` | The `pr` URL result value |
| `{{ index .Deps "implement" "Name" }}` | The dependency task name |

Agents automatically capture `branch`, `pr`, `commit`, `base-branch`,
`cost-usd`, `input-tokens`, and `output-tokens` as results. See the
[reference docs](../../docs/reference.md) for the full list.

## Steps

1. **Edit the secrets** β€” replace placeholders in both `github-token-secret.yaml`
and `credentials-secret.yaml` with your real tokens.

2. **Edit `workspace.yaml`** β€” set your repository URL and branch.

3. **Edit `tasks.yaml`** β€” customize the prompts for your feature.

4. **Apply the resources:**

```bash
kubectl apply -f examples/06-task-dependencies/
```

5. **Watch the pipeline progress:**

```bash
kubectl get tasks -w
```

You should see:

```
NAME TYPE PHASE AGE
implement claude-code Running 10s
write-tests claude-code Waiting 10s
review claude-code Waiting 10s
```

Then as `implement` succeeds:

```
NAME TYPE PHASE AGE
implement claude-code Succeeded 5m
write-tests claude-code Running 5m
review claude-code Waiting 5m
```

6. **Stream logs from a specific stage:**

```bash
axon logs implement -f
axon logs write-tests -f
```

7. **Cleanup:**

```bash
kubectl delete -f examples/06-task-dependencies/
```

## CLI Equivalent

You can create the same pipeline with `axon run`:

```bash
axon run -p "Add a /healthz endpoint" \
--name implement \
--branch feature/healthz

axon run -p "Write tests for the /healthz endpoint" \
--name write-tests \
--branch feature/healthz \
--depends-on implement

axon run -p "Review the changes and open a PR" \
--name review \
--branch feature/healthz \
--depends-on write-tests
```

## Notes

- All three tasks share the same `branch: feature/healthz`. Axon's branch
mutex guarantees that only one task runs on a given branch at a time,
even without `dependsOn`. The `dependsOn` field adds the additional
guarantee that a task only starts after its dependencies **succeed**
(not just finish).
- If `implement` fails, both `write-tests` and `review` fail immediately
Copy link

@cubic-dev-ai cubic-dev-ai bot Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Inaccurate failure propagation description. Since review depends on write-tests (not directly on implement), when implement fails the message on review would be "Dependency 'write-tests' failed", not "Dependency 'implement' failed". The failure also isn't truly "immediate" for review β€” it propagates through write-tests first.

Prompt for AI agents
Check if this issue is valid β€” if so, understand the root cause and fix it. At examples/06-task-dependencies/README.md, line 129:

<comment>Inaccurate failure propagation description. Since `review` depends on `write-tests` (not directly on `implement`), when `implement` fails the message on `review` would be *"Dependency 'write-tests' failed"*, not *"Dependency 'implement' failed"*. The failure also isn't truly "immediate" for `review` β€” it propagates through `write-tests` first.</comment>

<file context>
@@ -0,0 +1,133 @@
+  even without `dependsOn`. The `dependsOn` field adds the additional
+  guarantee that a task only starts after its dependencies **succeed**
+  (not just finish).
+- If `implement` fails, both `write-tests` and `review` fail immediately
+  with the message "Dependency 'implement' failed".
+- Prompt templates are resolved once, right before the Job is created.
</file context>
Fix with Cubic

with the message "Dependency 'implement' failed".
- Prompt templates are resolved once, right before the Job is created.
If a template variable cannot be resolved, the raw prompt is used as
a fallback.
8 changes: 8 additions & 0 deletions examples/06-task-dependencies/credentials-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: v1
kind: Secret
metadata:
name: claude-oauth-token
type: Opaque
stringData:
# TODO: Replace with your Claude OAuth token
CLAUDE_CODE_OAUTH_TOKEN: "REPLACE-ME"
9 changes: 9 additions & 0 deletions examples/06-task-dependencies/github-token-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: v1
kind: Secret
metadata:
name: github-token
type: Opaque
stringData:
# TODO: Replace with your GitHub Personal Access Token
# Required permissions: repo (for private repos), workflow (optional)
GITHUB_TOKEN: "ghp_REPLACE-ME"
68 changes: 68 additions & 0 deletions examples/06-task-dependencies/tasks.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Task dependency chain: implement -> test -> review
#
# - "implement" runs first and creates a branch with changes.
# - "write-tests" waits for "implement" to succeed, then adds tests on
# the same branch using the branch name from implement's outputs.
# - "review" waits for "write-tests" to succeed, then reviews the PR.
#
# All three tasks share the same branch, so they are also serialized by
# the branch mutex β€” only one runs at a time.

apiVersion: axon.io/v1alpha1
kind: Task
metadata:
name: implement
spec:
type: claude-code
# TODO: Replace with your feature description
prompt: |
Add a /healthz HTTP endpoint that returns 200 OK with a JSON body
containing the server version. Push your changes to the branch.
credentials:
type: oauth
secretRef:
name: claude-oauth-token
workspaceRef:
name: my-workspace
branch: feature/healthz
---
apiVersion: axon.io/v1alpha1
kind: Task
metadata:
name: write-tests
spec:
type: claude-code
# This prompt is a Go text/template. When "implement" succeeds, Axon
# resolves {{ index .Deps "implement" "Results" "branch" }} to the
# branch name captured from implement's outputs (e.g. "feature/healthz").
prompt: |
The implementation is on branch {{ index .Deps "implement" "Results" "branch" }}.
Write unit tests for the /healthz endpoint. Make sure all tests pass
before pushing.
credentials:
type: oauth
secretRef:
name: claude-oauth-token
workspaceRef:
name: my-workspace
branch: feature/healthz
dependsOn: [implement]
---
apiVersion: axon.io/v1alpha1
kind: Task
metadata:
name: review
spec:
type: claude-code
prompt: |
Review the changes on branch {{ index .Deps "write-tests" "Results" "branch" }}.
Open a pull request if one does not exist yet, then review it for
correctness, test coverage, and style. Leave comments on the PR.
credentials:
type: oauth
secretRef:
name: claude-oauth-token
workspaceRef:
name: my-workspace
branch: feature/healthz
dependsOn: [write-tests]
10 changes: 10 additions & 0 deletions examples/06-task-dependencies/workspace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: axon.io/v1alpha1
kind: Workspace
metadata:
name: my-workspace
spec:
# TODO: Replace with your repository URL
repo: https://github.com/your-org/your-repo.git
ref: main
secretRef:
name: github-token
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Ready-to-use patterns and YAML manifests for orchestrating AI agents with Axon.
| [03-taskspawner-github-issues](03-taskspawner-github-issues/) | Automatically create Tasks from labeled GitHub issues |
| [04-taskspawner-cron](04-taskspawner-cron/) | Run agent tasks on a cron schedule |
| [05-task-with-agentconfig](05-task-with-agentconfig/) | Inject reusable instructions and plugins via AgentConfig |
| [06-task-dependencies](06-task-dependencies/) | Chain tasks with `dependsOn` into a multi-stage pipeline |

## How to Use

Expand Down