Guidez l'utilisateur dans la création d'une nouvelle tâche Harbor de bout en bout. Ne dumpe pas juste des commandes — marchez-le à travers chaque décision, notamment autour du vérificateur (qui est généralement la partie la plus difficile).
Step 1: Scaffold the task
harbor task init "<org>/<task-name>"
Flags utiles :
--description "..."--author "Jane Doe <jane@example.com>"(répéter pour plusieurs auteurs)--no-pytest— sauter le template de test pytest (utiliser si vous prévoyez Reward Kit ou un vérificateur personnalisé)--no-solution— sauter le répertoire solution/--metadata-template path.toml— pré-remplir task.toml
Produit :
<task-name>/
├── instruction.md # Task prompt for the agent
├── task.toml # Config and metadata
├── environment/Dockerfile # Container definition
├── solution/solve.sh # Reference solution (optional)
└── tests/test.sh # Verifier script
Si l'utilisateur veut une tâche multi-étapes (étapes ordonnées avec des instructions par étape, des tests et un arrêt anticipé sur un conteneur partagé), scaffoldez d'abord la disposition à une seule étape, puis convertissez-la à la disposition steps/ décrite dans la section Multi-step tasks ci-dessous.
Step 2: Write instruction.md
C'est le prompt que l'agent reçoit. Aidez l'utilisateur à l'écrire clairement :
- Énoncez l'objectif concrètement — quel fichier créer, quel comportement produire
- Spécifiez les outputs attendus — chemins, formats, contenu
- Incluez les contraintes — langage, outils, approche
- Ne divulguez pas les tests — décrivez ce que « fait » signifie, pas comment vous le vérifierez
Exemple (du tutoriel ssh-key-pair) :
# SSH Key Pair Generation
Generate an SSH key pair in the files `~/.ssh/id_rsa` and `~/.ssh/id_rsa.pub`.
Don't make them password protected.
Step 3: Build the environment
Modifiez environment/Dockerfile pour installer les dépendances dont la tâche a besoin. L'agent travaille
à l'intérieur de ce conteneur.
FROM ubuntu:24.04
WORKDIR /app
# Install what the task requires — NOT the solution
RUN apt-get update && apt-get install -y openssh-client && rm -rf /var/lib/apt/lists/*
Pour les configurations multi-conteneurs, utilisez environment/docker-compose.yaml à la place (note : la plupart
des fournisseurs de sandbox cloud ne supportent que Dockerfile).
Testez l'environnement de manière interactive avant d'écrire la solution ou les tests :
harbor task start-env -p "<task-path>" -e docker -a -i
C'est généralement là que les auteurs de tâches réalisent que quelque chose manque dans le Dockerfile.
Step 4: Decide how to verify
C'est la décision la plus importante. Demandez à l'utilisateur : « Comment veux-tu noter cette tâche ? » Ensuite, aidez-le à choisir :
Demandez aussi : « Le vérificateur doit-il s'exécuter dans le même environnement que l'agent, ou dans un environnement de vérificateur séparé ? »
- Utilisez l'environnement partagé par défaut quand les tests doivent inspecter l'espace de travail complet de l'agent, les outils installés ou les services.
- Utilisez un environnement de vérificateur séparé quand la notation de code, les dépendances, les clés API ou les exigences du système d'exploitation doivent rester cachées à l'agent, ou quand la vérification doit s'exécuter à partir d'une image propre.
Pour un conteneur de vérificateur séparé, tests/ est le contexte de build d'image du vérificateur
et l'image doit fournir /tests/test.sh (Linux) ou /tests/test.bat
(Windows). Harbor copie /logs/artifacts et les artefacts configurés dans l'environnement du vérificateur, pas l'espace de travail complet de l'agent.
[verifier]
environment_mode = "separate"
[verifier.environment]
docker_image = "ubuntu:24.04"
Option A: Reward Kit (recommended for most cases)
À utiliser quand le vérificateur a plusieurs critères, a besoin de crédit partiel, utilise un juge LLM/agent, ou bénéficierait de vérifications réutilisables composables. Consultez la compétence rewardkit.
Signaux d'une bonne adaptation :
- Plusieurs choses à vérifier (le fichier existe + le contenu est correct + la commande fonctionne)
- Dimensions de qualité subjectives (lisibilité, correction de la prose)
- Vouloir un crédit partiel plutôt que réussite/échec
- Vouloir composer des built-ins comme
file_contains,command_succeeds,json_key_equals
tests/test.sh:
#!/bin/bash
uvx --from 'harbor-rewardkit==0.1.*' rewardkit /tests
Note : le package s'appelle harbor-rewardkit mais l'exécutable est rewardkit,
d'où --from 'harbor-rewardkit==0.1.*' rewardkit. Exécuter
uvx harbor-rewardkit directement échouera.
Ensuite, ajoutez tests/checks.py et/ou tests/judge.toml. Invoquez la compétence rewardkit pour
concevoir les critères.
Option B: pytest (good for deterministic unit-style checks)
À utiliser quand la vérification est une assertion Python simple. Template par défaut si
--no-pytest n'a pas été passé.
tests/test.sh:
#!/bin/bash
apt-get update && apt-get install -y curl
curl -LsSf https://astral.sh/uv/0.9.7/install.sh | sh
source $HOME/.local/bin/env
uvx --with pytest==8.4.1 pytest /tests/test_outputs.py
if [ $? -eq 0 ]; then
echo 1 > /logs/verifier/reward.txt
else
echo 0 > /logs/verifier/reward.txt
fi
Exemple tests/test_outputs.py:
from pathlib import Path
def test_file_exists():
assert (Path.home() / ".ssh" / "id_rsa").exists()
Option C: Custom shell
Pour les vérifications simples à une seule commande (par ex. un pass/fail binaire d'une commande) :
#!/bin/bash
if diff -q /app/output.txt /tests/expected.txt; then
echo 1 > /logs/verifier/reward.txt
else
echo 0 > /logs/verifier/reward.txt
fi
Reward file format (all options)
/logs/verifier/reward.txt— nombre unique (généralement0ou1)/logs/verifier/reward.json—{"accuracy": 0.95, "runtime_sec": 1.2}pour plusieurs métriques
Utilisez toujours des chemins absolus dans test.sh.
Step 5: Write the solution
Écrivez solution/solve.sh — un script qui résout réellement la tâche. L'agent Oracle exécute
ceci pour vérifier que la tâche est résoluble et que les tests passent sur une solution correcte.
#!/bin/bash
ssh-keygen -t rsa -f ~/.ssh/id_rsa -N ""
Rendez-le exécutable : chmod +x solution/solve.sh.
Step 6: Configure task.toml
Parcourez les champs importants :
[task]
name = "<org>/<task-name>"
description = "One-line description"
keywords = ["jax", "mnist", "rewardkit"] # always populate — used for search/filtering
[metadata]
difficulty = "easy" | "medium" | "hard"
category = "programming" | "machine-learning" | "gpu" | ...
tags = ["..."]
[environment]
cpus = 1 # CPU cores
memory_mb = 2048 # RAM in MB
storage_mb = 10240 # Disk in MB
allow_internet = true # Network access
[agent]
timeout_sec = 120.0 # How long the agent has
[verifier]
timeout_sec = 600.0 # How long tests have
Remplissez toujours keywords. Choisissez 3–8 tokens en minuscules couvrant le domaine
(langage/framework/famille de benchmark), le style du vérificateur (rewardkit,
judge-grading, pytest), et tout matériel notable (gpu). Ils sont surfacés dans
harbor datasets list et la recherche de registry.
Pour les juges Reward Kit ayant besoin de clés API :
[verifier.env]
ANTHROPIC_API_KEY = "${ANTHROPIC_API_KEY}"
Step 7: Verify with the Oracle agent
harbor run -p "<task-path>" -a oracle
Oracle exécute solution/solve.sh puis le vérificateur. La récompense devrait être 1.0. Si ce n'est pas le cas, déboguez dans cet ordre :
- Est-ce que
solve.shle résout vraiment ? (start-env -a -iet exécutez-le manuellement) - Le vérificateur détecte-t-il correctement la réussite ? (vérifiez la sortie
/logs/verifier/) - Les chemins sont-ils corrects ? (absolus vs relatifs)
- Les dépendances sont-elles installées dans le Dockerfile ?
Step 8: Test with a real agent (optional)
harbor run -p "<task-path>" -a terminus-2 -m anthropic/claude-sonnet-4-6
Si la tâche est trop facile (chaque modèle 1.0) ou impossible (chaque modèle 0.0), envisagez d'ajuster la difficulté.
Step 9: Update README.md (always the final step)
harbor task init laisse README.md comme un stub. Avant de terminer, remplissez-le pour que
les futurs humains (et agents) puissent comprendre la tâche sans lire chaque fichier.
Incluez :
- Ce que l'agent fait — un paragraphe, lien vers
instruction.md. - Environnement — image de base, packages clés installés, données cachées, matériel (GPU/CPU/RAM), timeout de l'agent.
- Vérificateur — pour les tâches Reward Kit, un tableau des dimensions de récompense avec type (programmtique / juge LLM / juge agent) et ce que chacun mesure ; comment ils sont agrégés.
- Layout — un arbre du répertoire de tâche avec des annotations d'une ligne.
- Running — les commandes concrètes
harbor run(Oracle + agent réel), avec le flag de fournisseur correct si la tâche a besoin d'un GPU.
Traitez cela comme de la documentation, pas du marketing — le lecteur veut savoir ce qu'il devrait modifier pour changer la tâche.
Multi-step tasks
À utiliser quand le travail se divise en phases ordonnées qui doivent être notées séparément, quand vous voulez un arrêt anticipé entre les phases, ou quand vous testez la capacité d'un agent à construire sur ses travaux antérieurs. Les étapes partagent un conteneur ; les fichiers persistent à travers les étapes.
Directory layout
Remplacez le instruction.md au niveau racine de la tâche, tests/ et solution/ par un
répertoire steps/ contenant un sous-répertoire par étape :
<task-name>/
├── task.toml
├── environment/Dockerfile # Built once, shared across all steps
├── steps/
│ ├── scaffold/
│ │ ├── instruction.md # Prompt for this step
│ │ ├── workdir/ # Uploaded to WORKDIR before the agent runs
│ │ │ └── setup.sh # Optional pre-agent hook (reserved filename)
│ │ ├── tests/test.sh # Per-step verifier
│ │ └── solution/solve.sh # Per-step Oracle solution (optional)
│ ├── implement/
│ │ └── ...
│ └── document/
│ └── ...
└── tests/ # Optional shared helpers + fallback test.sh
Le tests/ au niveau tâche est uploadé vers /tests pour la vérification de chaque étape, puis
le propre tests/ de l'étape est superposé (les fichiers avec le même nom gagnent). Utilisez ceci pour
les helpers partagés.
steps/{name}/workdir/setup.sh est un nom de fichier réservé : s'il est présent, il s'exécute
après l'upload du workdir/ et avant l'agent, en tant qu'utilisateur agent de l'étape,
avec cwd = WORKDIR. Une sortie non zéro abandonne l'étape et l'essai. Faites-le
rm -- "$0" sur sa dernière ligne si l'agent ne devrait pas le voir.
task.toml
schema_version = "1.1"
[task]
name = "<org>/<task-name>"
# How per-step rewards roll up into the trial-level verifier_result.
# "mean" (default): per-key mean across steps that produced a result.
# "final": the last step's verifier_result verbatim.
multi_step_reward_strategy = "mean"
[[steps]]
name = "scaffold" # Must match the directory under steps/
min_reward = 1.0 # Abort trial if this step's reward < 1.0
[steps.agent]
timeout_sec = 60.0 # Overrides task-level [agent].timeout_sec
[steps.verifier]
timeout_sec = 30.0
[[steps]]
name = "implement"
# Dict form gates on specific keys from a multi-dim reward:
min_reward = { correctness = 0.8, style = 0.5 }
[steps.agent]
timeout_sec = 120.0
[steps.verifier]
timeout_sec = 30.0
[[steps]]
name = "document"
[steps.agent]
timeout_sec = 60.0
[steps.verifier]
timeout_sec = 30.0
Les overrides par étape disponibles : agent.timeout_sec, agent.user,
verifier.timeout_sec, verifier.env, verifier.user,
verifier.environment_mode, verifier.environment, healthcheck.*,
artifacts. Les champs non définis reviennent aux valeurs au niveau tâche.
Choosing a reward strategy
"mean"— signal agrégé à travers toutes les étapes ; bon pour les récompenses de progrès continu."final"— le verifier_result de la dernière étape est la récompense d'essai. Correct quand la dernière étape est une vérification de bout en bout dont le dict représente déjà la tâche complète. Caveat : simin_rewarddéclenche un abandon anticipé,"final"utilise le résultat de l'étape abandonnée, pas la dernière étape prévue.
Artifacts
Les artifacts au niveau étape sont collectés dans steps/{name}/artifacts/ après la
vérification de cette étape. Les artefacts au niveau tâche et au niveau essai sont collectés à
chaque étape en plus des artefacts au niveau étape.
Oracle verification
harbor run -p "<task-path>" -a oracle exécute solution/solve.sh de chaque étape,
puis le vérificateur de chaque étape, dans l'ordre. La récompense d'essai devrait être 1.0 à travers la
stratégie d'agrégation.
Full reference + worked example
- Docs:
docs/content/docs/tasks/multi-step.mdx - Example task:
examples/tasks/hello-multi-step-advanced/
Special features (mention if relevant)
- MCP servers: Add
[[environment.mcp_servers]]in task.toml for agent tooling - Healthcheck: Add
[environment.healthcheck]for services that need to be ready - GPU: Set
environment.gpusand optionallyenvironment.gpu_types - Pre-built image: Set
environment.docker_imageinstead of building from Dockerfile - Non-root user: Set
agent.user/verifier.userfor isolation
Common pitfalls
- Oublier d'écrire le fichier reward → la tâche « réussit » silencieusement avec une récompense 0
- Utiliser des chemins relatifs dans
test.sh→ s'effondre quand Harbor l'exécute depuis un cwd différent - Installer la solution dans le Dockerfile → l'agent reçoit déjà la réponse
- Le script de test fuit dans
instruction.md→ l'agent voit la rubrique et les manipulations deviennent triviales - Oublier
chmod +x solution/solve.sh→ l'agent Oracle échoue - Laisser
keywords = []dans task.toml → la tâche est invisible aux recherches de registry - Laisser
README.mdcomme un stub → les coéquipiers n'ont aucun moyen de comprendre la tâche d'un coup d'œil