create-task

Par harbor-framework · harbor

Créer une nouvelle tâche Harbor pour évaluer des agents. À utiliser lorsque l'utilisateur souhaite

npx skills add https://github.com/harbor-framework/harbor --skill create-task

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éralement 0 ou 1)
  • /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 :

  1. Est-ce que solve.sh le résout vraiment ? (start-env -a -i et exécutez-le manuellement)
  2. Le vérificateur détecte-t-il correctement la réussite ? (vérifiez la sortie /logs/verifier/)
  3. Les chemins sont-ils corrects ? (absolus vs relatifs)
  4. 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 : si min_reward dé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.gpus and optionally environment.gpu_types
  • Pre-built image: Set environment.docker_image instead of building from Dockerfile
  • Non-root user: Set agent.user / verifier.user for 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.md comme un stub → les coéquipiers n'ont aucun moyen de comprendre la tâche d'un coup d'œil

Skills similaires