Custom Agents
Run an ACP agent from a GitHub repository
Custom agents run over ACP from a source repository containing a harbor-agent.json manifest.
Connect the repository from your profile settings before using a private one.
The template below intentionally omits source.ref, so Harbor starts from the repository's default
branch and records the resolved commit SHA in the stored job config:
{
"config": {
"retry": {
"exclude_exceptions": [
"AgentTimeoutError",
"VerifierTimeoutError",
"RewardFileNotFoundError",
"RewardFileEmptyError",
"VerifierOutputParseError",
"ApiUsageLimitError",
"AgentSafetyRefusalError"
],
"include_exceptions": []
},
"agents": [
{
"name": "acp",
"source": {
"path": ".",
"repo": "<github-owner>/<custom-agent-repo>",
"type": "github",
"manifest": "harbor-agent.json"
},
"model_name": "<model-provider>/<model-name>",
"secrets": ["<MODEL_API_KEY_ENV_VAR>"]
}
],
"datasets": [
{
"ref": "<dataset-ref>",
"name": "<dataset-org>/<dataset-name>",
"n_tasks": 3
}
],
"job_name": "<job-name>"
},
"job_secrets": {
"<MODEL_API_KEY_ENV_VAR>": "<model-api-key>"
},
"dry_run": false
}Replace every <...> value before submitting. To select an explicit revision, add
"ref": "<branch-tag-or-commit>" inside source.
The source rules are:
namemust beacpwhensourceis present.source.typemust begithub, andsource.repomust useowner/repoform.source.refis optional and accepts a branch, tag, or commit SHA. When omitted, Harbor resolves GitHubHEAD, which is the repository's configured default branch and is normallymain, then records the exact commit SHA in the stored config so retries stay reproducible.source.pathdefaults to.and selects the repository directory holding the agent project.source.manifestdefaults toharbor-agent.jsonand is resolved relative tosource.path.- Custom agents bring their own model credentials. Supply the key in
job_secretsor store it as a hosted secret, and name it in the agent'ssecretseither way. A custom agent readsHOSTED_INFERENCE_TOKENandHOSTED_INFERENCE_URLrather than the provider's own variables, so the selection is what decides which credential backs that token.
The source directory needs a locked Python project and a manifest:
{
"schema_version": 1,
"id": "<agent-id>",
"version": "<agent-version>",
"protocol": "acp",
"runtime": {
"kind": "python-uv",
"python": "3.12",
"project": ".",
"lockfile": "uv.lock",
"entrypoint": ["python", "-m", "<agent-module>"]
}
}schema_version must be 1, protocol must be acp, runtime.kind must be python-uv, and
runtime.python must be "3.12". The entrypoint must be an executable that speaks ACP over standard
input and output, and its first element is a command name rather than a path. Commit the manifest,
the project files, and uv.lock to the repository.
To check repository access, the ref, and the manifest without launching anything, send the same
request with "dry_run": true. A successful validation returns the resolved repository, the pinned
commit, the manifest identity, and the access mode.