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

# Agent auth resolution

> Choose models, secrets, endpoints, and API formats for your agents.

export const ModelLookup = ({endpoint}) => {
  const [model, setModel] = useState("openai/gpt-6.1-sol");
  const [result, setResult] = useState(null);
  const [error, setError] = useState("");
  const [loading, setLoading] = useState(false);
  const lookup = async event => {
    event.preventDefault();
    setLoading(true);
    setResult(null);
    setError("");
    try {
      const response = await fetch(`${endpoint}?model=${encodeURIComponent(model.trim())}`, {
        credentials: "omit",
        signal: AbortSignal.timeout(10000)
      });
      const data = await response.json();
      if (!response.ok) {
        setError(typeof data.detail === "string" ? data.detail : "Enter a model name without spaces (up to 1,024 characters).");
        return;
      }
      setResult(data);
    } catch {
      setError("Could not reach the model lookup API. Please try again shortly.");
    } finally {
      setLoading(false);
    }
  };
  return <div className="not-prose my-6 rounded-xl border border-zinc-200 p-5 dark:border-zinc-800">
      <form onSubmit={lookup}>
        <label htmlFor="model-lookup-input" className="mb-2 block text-sm font-medium">
          Model name
        </label>
        <div className="flex flex-col gap-3 sm:flex-row">
          <input id="model-lookup-input" name="model" type="text" value={model} onChange={event => {
    setModel(event.target.value);
    setResult(null);
    setError("");
  }} placeholder="provider/model-name" required maxLength={1024} disabled={loading} autoCapitalize="none" autoCorrect="off" spellCheck={false} className="min-w-0 flex-1 rounded-lg border border-zinc-300 bg-transparent px-3 py-2 font-mono text-sm focus:outline-none focus:ring-2 focus:ring-zinc-500 dark:border-zinc-700" />
          <button type="submit" disabled={loading || !model.trim()} className="rounded-lg bg-zinc-900 px-4 py-2 text-sm font-medium text-white disabled:opacity-50 dark:bg-zinc-100 dark:text-zinc-900">
            {loading ? "Looking up…" : "Look up model"}
          </button>
        </div>
      </form>
      <div aria-live="polite" aria-busy={loading}>
        {error && <p role="alert" className="mt-4 text-sm text-red-700 dark:text-red-400">
            {error}
          </p>}
        {result && <dl className="mt-5 space-y-3 border-t border-zinc-200 pt-4 dark:border-zinc-800">
            {[["Input model", result.input_model], ["Provider", result.provider], ["Parsed model", result.parsed_model], ["LiteLLM version", result.litellm_version]].map(([label, value]) => <div key={label}>
                <dt className="text-xs font-medium text-zinc-500 dark:text-zinc-400">{label}</dt>
                <dd className="mt-1 break-all font-mono text-sm">{value}</dd>
              </div>)}
          </dl>}
      </div>
    </div>;
};

## Model name parsing

Harbor uses LiteLLM to parse model slugs during setup. Use the **same LiteLLM model slug across all agents**.

Browse [Harbor Model Lookup](https://harbortoolkit.com/model?model=openai%2Fgpt-6-sol),
or enter a model name below to see its provider and parsed model name.

<ModelLookup endpoint="https://harbortoolkit.com/resolve" />

<Note>
  * **Input model (`-m`)** → Your original model name.
  * **Parsed provider** → Selects Harbor’s built-in credential and endpoint mappings.
  * **Parsed model ID** → Usually sent to the inference provider; adapters may transform it.
</Note>

Try `openai/gpt-6-sol`, `openrouter/openai/gpt-6-sol`,
`anthropic/claude-sonnet-5-5`, `deepseek/deepseek-v4-flash`, or
`fireworks_ai/accounts/my-account/models/my-custom-model`.

Model slugs that cannot be parsed by LiteLLM are forwarded directly to the agent.
Each agent adapter may then infer the provider from the model slug.

## Automatic Secret Collection

For recognized [providers](https://harbortoolkit.com/model?model=openai%2Fgpt-6-sol) and built-in [agents](https://harbortoolkit.com/agent?agent=codex), Harbor supports automatic secret
collection from host environment variables. This behavior is
agent and provider specific, unrelated host variables are not forwarded.

See your agent’s [auth settings](#inspecting-agent-auth-settings).

<div className="run-examples">
  <Tabs sync={false}>
    <Tab title="Provider Match">
      ```bash theme={"system"}
      export OPENROUTER_API_KEY="sk-or-v1-...1234"
      export HF_TOKEN="hf_...3456"
      harbor run \
        -t hello-world/hello-world \
        --agent codex \
        --model openrouter/openai/gpt-5.6-sol \
      ```

      <div className="run-example">
        <Accordion title="See collected secrets" id="codex-collected-secrets">
          ```text nocopy theme={"system"}
          Collected from host: OPENROUTER_API_KEY
          Not forwarded to agent: HF_TOKEN
          ```
        </Accordion>
      </div>
    </Tab>

    <Tab title="Agent Match">
      ```bash theme={"system"}
      export ANTHROPIC_API_KEY="sk-ant-api03-...9012"
      harbor run \
        -t hello-world/hello-world \
        --agent claude-code \
        --model vercel_ai_gateway/z-ai/glm-5.3
      ```

      <div className="run-example">
        <Accordion title="See collected secrets" id="claude-collected-secrets">
          ```text nocopy theme={"system"}
            Collected from host: ANTHROPIC_API_KEY
          ```
        </Accordion>
      </div>
    </Tab>

    <Tab title="Explicitly Provided">
      ```bash theme={"system"}
      harbor run \
        -t hello-world/hello-world \
        --agent mini-swe-agent \
        --model openai/gpt-6-sol \
        --agent-env OPENAI_API_KEY="sk-proj-...5678"
      ```

      <div className="run-example">
        <Accordion title="See collected secrets" id="cursor-collected-secrets">
          ```text nocopy theme={"system"}
            Collected from --agent-env: OPENAI_API_KEY
          ```
        </Accordion>
      </div>
    </Tab>
  </Tabs>
</div>

<Accordion title="Common automatic secret collection">
  | Provider | Recognized host variables |
  | - | - |
  | `openai`, `openai-responses` | `OPENAI_API_KEY` |
  | `anthropic` | `ANTHROPIC_API_KEY` |
  | `openrouter` | `OPENROUTER_API_KEY` |
  | `gemini`, `google` | `GOOGLE_API_KEY`, `GEMINI_API_KEY`, `GOOGLE_GENERATIVE_AI_API_KEY` |
  | `azure` | `AZURE_API_KEY`, `AZURE_OPENAI_API_KEY` |
  | `amazon-bedrock`, `bedrock` | `AWS_BEARER_TOKEN_BEDROCK` and standard AWS credential variables |
  | `vercel_ai_gateway`, `vercel` | `VERCEL_AI_GATEWAY_API_KEY`, `AI_GATEWAY_API_KEY` |
  | `meta` | `META_API_KEY`, `MODEL_API_KEY` |
  | `xai` | `XAI_API_KEY` |
  | `mistral` | `MISTRAL_API_KEY` |
  | `deepseek` | `DEEPSEEK_API_KEY` |
  | `groq` | `GROQ_API_KEY` |
  | `kimi` | `KIMI_API_KEY`, `MOONSHOT_API_KEY` |
  | `moonshot` | `MOONSHOT_API_KEY` |
  | `huggingface` | `HF_TOKEN`, `HUGGINGFACE_API_KEY` |
  | `together`, `together_ai` | `TOGETHER_API_KEY`, `TOGETHERAI_API_KEY` |
  | `fireworks_ai` | `FIREWORKS_API_KEY` |
  | `nvidia` | `NVIDIA_API_KEY` |
  | `opencode` | `OPENCODE_API_KEY` |

  These agent-specific variables are recognized in addition to provider variables.

  | Agent | Recognized host variables |
  | - | - |
  | `codex` | `OPENAI_API_KEY`, `CODEX_API_KEY` |
  | `claude-code` | `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, `CLAUDE_CODE_OAUTH_TOKEN` |
  | `gemini-cli` | `GEMINI_API_KEY` |
  | `antigravity-cli` | `GEMINI_API_KEY`, `GOOGLE_API_KEY` |
  | `antigravity-sdk` | `GEMINI_API_KEY` |
  | `copilot-cli` | `COPILOT_GITHUB_TOKEN`, `GH_TOKEN`, `GITHUB_TOKEN`; custom providers: `COPILOT_PROVIDER_API_KEY`, `COPILOT_PROVIDER_BEARER_TOKEN` |
  | `cursor-cli` | `CURSOR_API_KEY` |
  | `fx` | `AI_GATEWAY_API_KEY`, `VERCEL_AI_GATEWAY_API_KEY`, `VERCEL_OIDC_TOKEN` |
  | `muse-code` | `META_API_KEY` |
  | `openhands`, `openhands-sdk` | `LLM_API_KEY` |
  | `mini-swe-agent` | `MSWEA_API_KEY` |
  | `goose`, `mimo`, `opencode`, `pi`, `qwen-coder`, `trae-agent` | `OPENAI_API_KEY` |

  ACP registry agents do not use this automatic forwarding; always pass their credentials
  with `--agent-env`.
</Accordion>

## Automatic Secret Routing

For built-in agents, Harbor automatically matches model provider secrets to the expected agent api key name.
This means you can use your `OPENROUTER_API_KEY` even though Codex reads `OPENAI_API_KEY`;
Harbor handles the rename for you.

For example, when using OpenRouter with Codex, **Codex only expects** the API key in
`OPENAI_API_KEY`. Harbor assigns the value of `OPENROUTER_API_KEY` to
`OPENAI_API_KEY` so Codex can authenticate with OpenRouter.

This lets you use one provider key, such as `OPENROUTER_API_KEY`, across multiple
agents without knowing each agent's native credential variable name. It is
especially useful for benchmark sweeps that compare different agents using the
same model and provider.

<div className="run-examples">
  <Tabs sync={false}>
    <Tab title="Provider Match">
      ```bash theme={"system"}
      export OPENROUTER_API_KEY="sk-or-v1-...1234"
      export HF_TOKEN="hf_...3456"
      harbor run \
        -t hello-world/hello-world \
        --agent codex \
        --model openrouter/openai/gpt-5.6-sol \
      ```

      <div className="run-example">
        <Accordion title="See routed secrets" id="codex-routed-secrets">
          ```text nocopy theme={"system"}
            Collected from host: OPENROUTER_API_KEY
            Automatic Routing: OPENROUTER_API_KEY -> OPENAI_API_KEY
            Codex reads: OPENAI_API_KEY
          ```
        </Accordion>
      </div>
    </Tab>

    <Tab title="Agent Match">
      ```bash theme={"system"}
      export ANTHROPIC_API_KEY="sk-ant-api03-...9012"
      harbor run \
        -t hello-world/hello-world \
        --agent claude-code \
        --model vercel_ai_gateway/z-ai/glm-5.3
      ```

      <div className="run-example">
        <Accordion title="See routed secrets" id="claude-routed-secrets">
          ```text nocopy theme={"system"}
            Collected from host: ANTHROPIC_API_KEY
            Automatic Routing: ANTHROPIC_API_KEY -> ANTHROPIC_API_KEY (nop)
            Claude Code reads: ANTHROPIC_API_KEY
          ```
        </Accordion>
      </div>
    </Tab>

    <Tab title="Explicitly Provided">
      ```bash theme={"system"}
      harbor run \
        -t hello-world/hello-world \
        --agent mini-swe-agent \
        --model openai/gpt-6-sol \
        --agent-env OPENAI_API_KEY="sk-proj-...5678"
      ```

      <div className="run-example">
        <Accordion title="See routed secrets" id="cursor-routed-secrets">
          ```text nocopy theme={"system"}
            Collected from --agent-env: OPENAI_API_KEY
            Automatic Routing: OPENAI_API_KEY -> OPENAI_API_KEY (nop)
            Mini SWE Agent reads: OPENAI_API_KEY
          ```
        </Accordion>
      </div>
    </Tab>
  </Tabs>
</div>

## Automatic Secret Routing rules

<Tip>
  **Recommended: use `--dry-run` first.** You don't need to understand all the routing
  rules—it shows the resolved credential, endpoint, model, and API format.
</Tip>

When multiple secrets are supplied that match either the provider or the agent, Harbor
uses the following precedence rules to determine which secret is utilized.

1. `--api-key-name ENV_VAR_NAME`
2. `--agent-env ENV_VAR_NAME` matching the parsed model slug's provider
3. `--agent-env ENV_VAR_NAME` matching the chosen agent's declared defaults
4. Host environment variables matching the parsed model slug's provider
5. Host environment variables matching the chosen agent's declared provider

Use `harbor run --dry-run` to see which variable will be chosen in order of precedence.

<div className="run-examples">
  <Tabs sync={false}>
    <Tab title="OpenAI">
      ```bash theme={"system"}
      export OPENAI_API_KEY="sk-proj-...5678"
      harbor run --dry-run \
        -t hello-world/hello-world \
        -a codex \
        -m openai/gpt-6-sol
      ```

      <div className="run-example run-example-run">
        <Accordion title="▶ Run" id="routing-rules-openai-output">
          <div className="auth-resolution-table">
            | Setting | Value |
            | - | - |
            | Parsed provider | `openai` |
            | Resolved model | `gpt-6-sol` |
            | Endpoint | `https://api.openai.com/v1` |
            | API format | `openai_responses` |
            | API key precedence | `1. --api-key-name — not set`<br />`2. --ae OPENAI_API_KEY — not set`<br />`3. --ae CODEX_API_KEY — not set`<br />`4. ambient OPENAI_API_KEY — selected (********5678)`<br />`5. ambient CODEX_API_KEY — not set` |
            | Base URL precedence | `1. --base-url — not set`<br />`2. --ae OPENAI_BASE_URL — not set`<br />`3. --ae OPENAI_API_BASE — not set`<br />`4. ambient OPENAI_BASE_URL — not set`<br />`5. ambient OPENAI_API_BASE — not set`<br />`6. Default base URL — selected (https://api.openai.com/v1)` |
          </div>
        </Accordion>
      </div>
    </Tab>

    <Tab title="Provider precedence">
      ```bash theme={"system"}
      export OPENAI_API_KEY="sk-proj-...5678"
      export OPENROUTER_API_KEY="sk-or-v1-...1234"
      harbor run --dry-run \
        -t hello-world/hello-world \
        -a codex \
        -m openrouter/openai/gpt-6-sol
      ```

      <div className="run-example run-example-run">
        <Accordion title="▶ Run" id="routing-rules-provider-output">
          <div className="auth-resolution-table">
            | Setting | Value |
            | - | - |
            | Parsed provider | `openrouter` |
            | Resolved model | `openai/gpt-6-sol` |
            | Endpoint | `https://openrouter.ai/api/v1` |
            | API format | `openai_responses` |
            | API key precedence | `1. --api-key-name — not set`<br />`2. --ae OPENROUTER_API_KEY — not set`<br />`3. --ae OPENAI_API_KEY — not set`<br />`4. --ae CODEX_API_KEY — not set`<br />`5. ambient OPENROUTER_API_KEY — selected (********1234)`<br />`6. ambient OPENAI_API_KEY — not selected (********5678)`<br />`7. ambient CODEX_API_KEY — not set` |
            | Base URL precedence | `1. --base-url — not set`<br />`2. --ae OPENROUTER_BASE_URL — not set`<br />`3. --ae OPENAI_BASE_URL — not set`<br />`4. ambient OPENROUTER_BASE_URL — not set`<br />`5. ambient OPENAI_BASE_URL — not set`<br />`6. Default base URL — selected (https://openrouter.ai/api/v1)` |
          </div>
        </Accordion>
      </div>
    </Tab>

    <Tab title="Explicit overrides">
      ```bash theme={"system"}
      export OPENAI_API_KEY="sk-proj-...5678"
      export OPENROUTER_API_KEY="sk-or-v1-...1234"
      harbor run --dry-run \
        -t hello-world/hello-world \
        -a codex \
        -m openrouter/openai/gpt-6-sol \
        --ae NEW_ENV_VAR="sk-or-v1-...7890" \
        --api-key-name NEW_ENV_VAR \
        --base-url https://directly-supplied-url.fake
      ```

      <div className="run-example run-example-run">
        <Accordion title="▶ Run" id="routing-rules-explicit-output">
          <div className="auth-resolution-table">
            | Setting | Value |
            | - | - |
            | Parsed provider | `openrouter` |
            | Resolved model | `openai/gpt-6-sol` |
            | Endpoint | `https://directly-supplied-url.fake` |
            | API format | `openai_responses` |
            | API key precedence | `1. --api-key-name NEW_ENV_VAR — selected (********7890)`<br />`2. --ae OPENROUTER_API_KEY — not set`<br />`3. --ae OPENAI_API_KEY — not set`<br />`4. --ae CODEX_API_KEY — not set`<br />`5. ambient OPENROUTER_API_KEY — not selected (********1234)`<br />`6. ambient OPENAI_API_KEY — not selected (********5678)`<br />`7. ambient CODEX_API_KEY — not set` |
            | Base URL precedence | `1. --base-url — selected (https://directly-supplied-url.fake)`<br />`2. --ae OPENROUTER_BASE_URL — not set`<br />`3. --ae OPENAI_BASE_URL — not set`<br />`4. ambient OPENROUTER_BASE_URL — not set`<br />`5. ambient OPENAI_BASE_URL — not set`<br />`6. Default base URL — not selected (https://openrouter.ai/api/v1)` |
          </div>
        </Accordion>
      </div>
    </Tab>
  </Tabs>
</div>

Use the **Model Auth Override** options in `harbor run`, `harbor job start`, or
`harbor trial start` when you need a different endpoint, credential variable,
or API format:

| CLI option | AgentConfig field | Purpose |
| - | - | - |
| `--base-url` | `model_base_url` | Set the inference endpoint. |
| `--api-key-name` | `model_api_key_name` | Read the key from this environment variable. |
| `--api-format` | `model_api_format` | Select a supported API format. |

<Note>
  `--base-url`, `--api-key-name`, and `--api-format` can each be
  used independently, **without `--skip-model-parsing-and-provider-mapping`**. When you enable
  `--skip-model-parsing-and-provider-mapping`, you will typically use these overrides together to
  specify the endpoint, credential variable, and API format explicitly.
</Note>

Base URL environment variable injection follows the same selection and routing rules as credentials.

## Advanced

### Parsing and credential mapping under the hood

LiteLLM splits the model name into a provider and model ID. Harbor then looks up
that provider in `PROVIDERS` and combines its credential and endpoint candidates
with the agent's declared fallbacks and any explicit overrides. If parsing does
not identify a provider, Harbor uses the agent's `default_provider`.

After applying precedence, Harbor writes the selected credential value to the
agent's declared destination. In this Codex example, the value of
`OPENROUTER_API_KEY` is injected as `OPENAI_API_KEY`.

<div className="dark:hidden">
  <img src="https://mintcdn.com/harborframework/XgpEiBorN2ZNCFHj/images/agent-auth-resolution/parsing-and-routing-light.svg?fit=max&auto=format&n=XgpEiBorN2ZNCFHj&q=85&s=2c91afe106dfd2df7628682f201ab9a2" alt="Model parsing and credential routing: LiteLLM identifies OpenRouter, Harbor applies overrides then provider credentials then Codex fallbacks, and injects the selected value into OPENAI_API_KEY." width="1870" height="1670" data-path="images/agent-auth-resolution/parsing-and-routing-light.svg" />
</div>

<div className="hidden dark:block">
  <img src="https://mintcdn.com/harborframework/XgpEiBorN2ZNCFHj/images/agent-auth-resolution/parsing-and-routing-dark.svg?fit=max&auto=format&n=XgpEiBorN2ZNCFHj&q=85&s=e3e38b0dca0469eb9c403a9158baa766" alt="Model parsing and credential routing: LiteLLM identifies OpenRouter, Harbor applies overrides then provider credentials then Codex fallbacks, and injects the selected value into OPENAI_API_KEY." width="1870" height="1670" data-path="images/agent-auth-resolution/parsing-and-routing-dark.svg" />
</div>

### Skipping model parsing and credential mapping

In certain cases, such as hosting a local model, it may be necessary to skip the model
name parsing and subsequent credential mapping. To accomplish this, use `--skip-model-parsing-and-provider-mapping` (or `--sm`)
in your `harbor run` command.

With `--skip-model-parsing-and-provider-mapping`, Harbor preserves the model name exactly and uses
`harbor-skip-parsing` as the provider marker. The red steps above
(LiteLLM parsing and provider mapping) are skipped.
The agent's declared fallbacks, explicit overrides, precedence, and credential
injection still apply.

In this example, `--api-key-name CUSTOM_KEY` selects the value of
`CUSTOM_KEY`, which Codex receives as `OPENAI_API_KEY`. Skipping parsing does not
disable this final injection step.

<div className="dark:hidden">
  <img src="https://mintcdn.com/harborframework/XgpEiBorN2ZNCFHj/images/agent-auth-resolution/skip-parsing-light.svg?fit=max&auto=format&n=XgpEiBorN2ZNCFHj&q=85&s=36c2ce26f146ff291aab2b37e0bf9ebc" alt="Skipping model parsing: the local model path is preserved, provider lookup is bypassed, and an explicit CUSTOM_KEY override is injected into Codex as OPENAI_API_KEY." width="1690" height="1035" data-path="images/agent-auth-resolution/skip-parsing-light.svg" />
</div>

<div className="hidden dark:block">
  <img src="https://mintcdn.com/harborframework/XgpEiBorN2ZNCFHj/images/agent-auth-resolution/skip-parsing-dark.svg?fit=max&auto=format&n=XgpEiBorN2ZNCFHj&q=85&s=e042cf65ffd3930055c8eab2abc86c79" alt="Skipping model parsing: the local model path is preserved, provider lookup is bypassed, and an explicit CUSTOM_KEY override is injected into Codex as OPENAI_API_KEY." width="1690" height="1035" data-path="images/agent-auth-resolution/skip-parsing-dark.svg" />
</div>

### Inspecting agent auth settings

Browse [Harbor Agent Auth Lookup](https://harbortoolkit.com/agent)
to see each agent’s credential mappings, default endpoints, and supported API format overrides.

Use `harbor agent auth <agent>` to inspect an agent's default provider, credential
and endpoint routing, and supported API formats.

<div className="run-examples">
  <Tabs sync={false}>
    <Tab title="Grok Build">
      ```bash theme={"system"}
      harbor agent auth grok-build
      ```

      <div className="run-example run-example-run">
        <Accordion title="▶ Run" id="agent-auth-grok-build-output">
          <div className="auth-resolution-table">
            **Harbor provider defaults (bypassed by `--skip-model-parsing-and-provider-mapping`)**

            | Setting | Value |
            | - | - |
            | Default provider | `xai` |
            | Default base URL | `https://api.x.ai/v1` |
            | Provider API key names | `XAI_API_KEY` |
            | Provider base URL names | `XAI_BASE_URL` |
            | Provider extra environment variables | none |

            **Agent connection settings**

            | Setting | Contract |
            | - | - |
            | Default API key names | `XAI_API_KEY` |
            | API key injected into | `default: XAI_API_KEY`<br />`openai_chat_completions: OPENAI_API_KEY`<br />`openai_responses: OPENAI_API_KEY`<br />`anthropic_messages: ANTHROPIC_API_KEY` |
            | Default base URL name | `XAI_BASE_URL` |
            | Base URL injected into | unknown |
            | Supported API formats | `openai_chat_completions`, `openai_responses`, `anthropic_messages` |
            | Default API formats | `default: openai_chat_completions`<br />`openai: openai_responses`<br />`anthropic: anthropic_messages`<br />`openrouter: openai_chat_completions` |
            | Accepts custom base URL | yes (`--base-url`) |
            | Accepts credential selector | yes (`--api-key-name`) |
          </div>
        </Accordion>
      </div>
    </Tab>

    <Tab title="Codex">
      ```bash theme={"system"}
      harbor agent auth codex
      ```

      <div className="run-example run-example-run">
        <Accordion title="▶ Run" id="agent-auth-codex-output">
          <div className="auth-resolution-table">
            **Harbor provider defaults (bypassed by `--skip-model-parsing-and-provider-mapping`)**

            | Setting | Value |
            | - | - |
            | Default provider | `openai` |
            | Default base URL | `https://api.openai.com/v1` |
            | Provider API key names | `OPENAI_API_KEY` |
            | Provider base URL names | `OPENAI_BASE_URL`, `OPENAI_API_BASE` |
            | Provider extra environment variables | none |

            **Agent connection settings**

            | Setting | Contract |
            | - | - |
            | Default API key names | `OPENAI_API_KEY`, `CODEX_API_KEY` |
            | API key injected into | `default: OPENAI_API_KEY` |
            | Default base URL name | `OPENAI_BASE_URL` |
            | Base URL injected into | `default: OPENAI_BASE_URL` |
            | Supported API formats | `openai_responses` |
            | Default API formats | `default: openai_responses` |
            | Accepts custom base URL | yes (`--base-url`) |
            | Accepts credential selector | yes (`--api-key-name`) |
          </div>
        </Accordion>
      </div>
    </Tab>

    <Tab title="Mini SWE Agent">
      ```bash theme={"system"}
      harbor agent auth mini-swe-agent
      ```

      <div className="run-example run-example-run">
        <Accordion title="▶ Run" id="agent-auth-mini-swe-agent-output">
          <div className="auth-resolution-table">
            **Harbor provider defaults (bypassed by `--skip-model-parsing-and-provider-mapping`)**

            | Setting | Value |
            | - | - |
            | Default provider | none |
            | Default base URL | none |
            | Provider API key names | none |
            | Provider base URL names | none |
            | Provider extra environment variables | none |

            **Agent connection settings**

            | Setting | Contract |
            | - | - |
            | Default API key names | `MSWEA_API_KEY` |
            | API key injected into | Determined by model slug and API format |
            | Default base URL name | `OPENAI_BASE_URL`, `OPENAI_API_BASE` |
            | Base URL injected into | `default: OPENAI_BASE_URL`<br />`anthropic_messages: ANTHROPIC_API_BASE` |
            | Supported API formats | `openai_chat_completions`, `openai_responses`, `anthropic_messages` |
            | Default API formats | `gemini: google_generate_content`<br />`amazon-bedrock: bedrock_converse` |
            | Accepts custom base URL | yes (`--base-url`) |
            | Accepts credential selector | yes (`--api-key-name`) |
          </div>
        </Accordion>
      </div>
    </Tab>
  </Tabs>
</div>

### Selecting API formats

An API format defines how the agent communicates with the model provider.
Claude Code supports only Anthropic Messages, while agents such as Grok Build
support multiple formats. Harbor selects the agent's default format for the
provider identified by LiteLLM.

Use `--api-format` to override this default. Values are `openai_responses`,
`openai_chat_completions`, `anthropic_messages`, `google_generate_content`, and
`bedrock_converse`. Each agent accepts only the formats it supports.

### Routing across API formats

The provider determines where Harbor looks for credentials and which endpoint it
uses. The agent's selected API format determines how it sends requests and which
variable receives the credential. These can differ even for the same agent.

Some agents read the same credential variable for every provider; others change
it based on the API format. Grok Build is an example of the latter:

| Model provider | API format | Credential routing |
| - | - | - |
| `anthropic` | Anthropic Messages | `ANTHROPIC_API_KEY` → `ANTHROPIC_API_KEY` |
| `openai` | OpenAI Responses | `OPENAI_API_KEY` → `OPENAI_API_KEY` |
| `openrouter` | OpenAI Chat Completions | `OPENROUTER_API_KEY` → `OPENAI_API_KEY` |

In the OpenRouter case, `OPENAI_API_KEY` is the variable Grok Build reads; requests
still go to OpenRouter using the OpenRouter credential.

For a custom endpoint, use `--api-format` to select its protocol,
`--api-key-name` to select the credential source, and `--base-url`
to select the endpoint. The agent still determines the destination variable.

### Local Models

Local models may require explicit routing to preserve the model name and select
the endpoint and credential. This Codex example assumes a vLLM server with
Responses and tool calling support, serving the model as `/dev/shm/my-model`:

```bash theme={"system"}
export VLLM_API_KEY="dummy"
harbor run \
  -t hello-world/hello-world \
  -a codex \
  -m /dev/shm/my-model \
  --skip-model-parsing-and-provider-mapping \
  --api-key-name VLLM_API_KEY \
  --base-url http://host.docker.internal:8000/v1
```

vLLM does not require authentication by default; if you enable `--api-key`, set
`VLLM_API_KEY` to that value. Replace the URL with your server's address as seen
from the agent environment. `host.docker.internal` reaches the host from Docker
on macOS; `localhost` inside the agent refers to its own container.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.