> ## Documentation Index
> Fetch the complete documentation index at: https://docs.harborframework.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 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:

```json theme={"system"}
{
  "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:

* `name` must be `acp` when `source` is present.
* `source.type` must be `github`, and `source.repo` must use `owner/repo` form.
* `source.ref` is optional and accepts a branch, tag, or commit SHA. When omitted, Harbor resolves
  GitHub `HEAD`, which is the repository's configured default branch and is normally `main`, then
  records the exact commit SHA in the stored config so retries stay reproducible.
* `source.path` defaults to `.` and selects the repository directory holding the agent project.
* `source.manifest` defaults to `harbor-agent.json` and is resolved relative to `source.path`.
* Custom agents bring their own model credentials. Supply the key in `job_secrets` or store it
  as a hosted secret, and name it in the agent's [`secrets`](/core-concepts/hosted-harbor/submitting-jobs#agent-secrets) either way. A custom
  agent reads `HOSTED_INFERENCE_TOKEN` and `HOSTED_INFERENCE_URL` rather 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:

```json theme={"system"}
{
  "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.
