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

# Deploying Agents with GitHub Actions

> Automate agent deployment using the Runloop deploy-agent GitHub Action

<Tip>Start with the [Runloop Quickstart](/docs/tutorials/quickstart) to understand the basics of agents.</Tip>

## Overview

Runloop's [deploy-agent GitHub Action](https://github.com/runloopai/deploy-agent) automates agent deployment directly from your GitHub workflows. It provides a convenient way to deploy agents without writing custom API integration code, while maintaining the same functionality as the [Agents API](/docs/devboxes/agents/using-agents-api).

### Key Features

* **Zero-config Git deployments** - Automatically deploys your current repository
* **Release tag support** - Deploys specific versions when releases are published
* **Multiple source types** - Git repositories, npm packages, pip packages, tar archives, and single files
* **Flexible packaging** - Create tar archives however you want in your workflow
* **Setup commands** - Run custom setup commands after agent installation
* **Public/private agents** - Control agent visibility
* **TTL support** - Set expiration time for uploaded objects

## Quick Start

### Basic Git Deployment

Deploy your current repository as an agent with minimal configuration.

```yaml theme={null}
name: Deploy Agent

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Deploy agent
        uses: runloopai/deploy-agent@main
        with:
          api-key: ${{ secrets.RUNLOOP_API_KEY }}
          source-type: git
```

## Authentication

### Setting Up Your API Key

1. Go to the [Settings page](https://platform.runloop.ai/settings#api-keys) in the Runloop Dashboard
2. Create a new API key. For CI/CD workflows, consider using a [restricted key](https://platform.runloop.ai/settings#restricted-keys) scoped to only the resources the workflow needs (for example, Agents: write, Objects: write).
3. Add it as a GitHub secret:
   * Go to your repository's **Settings** → **Secrets and variables** → **Actions**
   * Click **New repository secret**
   * Name: `RUNLOOP_API_KEY`
   * Value: Your Runloop API key
   * Click **Add secret**

## Relationship to Agents API

The GitHub Action provides a convenient wrapper around the [Agents API](/docs/devboxes/agents/using-agents-api).

1. **For Git sources**: Creates an agent with `source.type: "git"` and the repository/ref information. When using the API directly, use the `ref` field for versioning instead of the top-level `version` — see [Agent Versioning](/docs/devboxes/agents/using-agents-api#agent-versioning).
2. **For Tar/File sources**:
   * Can upload the file/archive as a storage object
   * Creates an agent with `source.type: "object"` referencing the uploaded object
   * Applies any setup commands as `agent_setup` in the object source

### Equivalent API Calls

The GitHub Action deployment.

```yaml theme={null}
- uses: runloopai/deploy-agent@main
  with:
    api-key: ${{ secrets.RUNLOOP_API_KEY }}
    source-type: git
    setup-commands: |
      npm install
```

Is equivalent to this API call.

<CodeGroup>
  ```python Python theme={null}
  agent = await runloop.agent.create(
    name="repository-name",
    source={
      "type": "git",
      "git": {
        "repository": "https://github.com/user/repo",
        "ref": "main",
        "agent_setup": ["npm install"]
      }
    }
  )
  ```

  ```typescript TypeScript theme={null}
  const agent = await runloop.agent.create({
    name: 'repository-name',
    source: {
      type: 'git',
      git: {
        repository: 'https://github.com/user/repo',
        ref: 'main',
        agentSetup: ['npm install']
      }
    }
  });
  ```
</CodeGroup>

For tar/file sources, the action first uploads the object, then creates the agent.

<CodeGroup>
  ```python Python theme={null}
  # Step 1: Upload object (done automatically by action)
  storage_object = await runloop.storage_object.upload_from_file(
    file_path='./agent.tar.gz',
    name='agent.tar.gz'
  )

  # Step 2: Create agent from object (done automatically by action)
  agent = await runloop.agent.create(
    name="repository-name",
    source={
      "type": "object",
      "object": {
        "object_id": storage_object.id,
        "agent_setup": ["npm install"]
      }
    }
  )
  ```

  ```typescript TypeScript theme={null}
  // Step 1: Upload object (done automatically by action)
  const storageObject = await runloop.storageObject.uploadFromFile(
    './agent.tar.gz',
    'agent.tar.gz'
  );

  // Step 2: Create agent from object (done automatically by action)
  const agent = await runloop.agent.create({
    name: 'repository-name',
    source: {
      type: 'object',
      object: {
        objectId: storageObject.id,
        agentSetup: ['npm install']
      }
    }
  });
  ```
</CodeGroup>

## Input Parameters

| Input              | Required | Default                  | Description                                                                                                  |
| ------------------ | -------- | ------------------------ | ------------------------------------------------------------------------------------------------------------ |
| `api-key`          | ✅        | -                        | Runloop API key (store in secrets)                                                                           |
| `source-type`      | ✅        | -                        | Agent source type: `git`, `npm`, `pip`, `tar`, or `file`                                                     |
| `agent-version`    | ❌        | -                        | For npm/pip agents, pins the installed package version (e.g., `2.1.123`). Not used for git or object agents. |
| `agent-name`       | ❌        | Repository name          | Name for the agent (defaults to repository name)                                                             |
| `git-repository`   | ❌        | Current repo             | Git repository URL (auto-detected for `git` source)                                                          |
| `git-ref`          | ❌        | Current ref              | Git ref (branch or tag, auto-detected for `git` source)                                                      |
| `npm-package`      | ❌        | -                        | npm package name (required for `npm` source, e.g., `@anthropic-ai/claude-code`)                              |
| `npm-registry-url` | ❌        | -                        | Custom npm registry URL (optional, defaults to public npm)                                                   |
| `pip-package`      | ❌        | -                        | PyPI package name (required for `pip` source, e.g., `my-agent`)                                              |
| `pip-index-url`    | ❌        | -                        | Custom PyPI index URL (optional, defaults to public PyPI)                                                    |
| `path`             | ❌        | -                        | Path to tar archive or single file (required for `tar`/`file` source types)                                  |
| `content-type`     | ❌        | Auto-detected            | Object content type override (`unspecified`, `text`, `binary`, `gzip`, `tar`, `tgz`)                         |
| `setup-commands`   | ❌        | -                        | Newline-separated setup commands to run after installation                                                   |
| `api-url`          | ❌        | `https://api.runloop.ai` | Runloop API URL                                                                                              |
| `object-ttl-days`  | ❌        | -                        | Time-to-live for uploaded objects in days                                                                    |

### Outputs

| Output       | Description                                                     |
| ------------ | --------------------------------------------------------------- |
| `agent-id`   | The ID of the created agent (e.g., `agt_xxxx`)                  |
| `agent-name` | The name of the created agent                                   |
| `object-id`  | The ID of the uploaded object (if applicable, e.g., `obj_xxxx`) |

## Using Deployment Outputs

Capture and use the agent ID and other outputs from the deployment.

```yaml theme={null}
name: Deploy and Use Agent

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Deploy agent
        id: deploy
        uses: runloopai/deploy-agent@main
        with:
          api-key: ${{ secrets.RUNLOOP_API_KEY }}
          source-type: git
      
      - name: Use agent ID
        run: |
          echo "Agent ID: ${{ steps.deploy.outputs.agent-id }}"
          echo "Agent Name: ${{ steps.deploy.outputs.agent-name }}"
          
          # Use the agent ID in subsequent steps
          # For example, create a devbox with this agent
```

## Deployment Examples

### Git Source (Auto-detect)

Deploy the current repository as an agent. The action automatically detects the repository and tag.

```yaml theme={null}
name: Deploy Agent

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Deploy agent
        uses: runloopai/deploy-agent@main
        with:
          api-key: ${{ secrets.RUNLOOP_API_KEY }}
          source-type: git
          setup-commands: |
            chmod +x scripts/agent.sh
            npm install
```

### Git Source (On Release)

Deploy an agent when a new release is published, using the release tag as the agent name:

```yaml theme={null}
name: Deploy Agent on Release

on:
  release:
    types: [published]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Deploy agent
        uses: runloopai/deploy-agent@main
        with:
          api-key: ${{ secrets.RUNLOOP_API_KEY }}
          source-type: git
          agent-name: my-agent-${{ github.event.release.tag_name }}
```

### Git Source (Custom Repository)

Deploy an agent from a specific Git repository and branch:

```yaml theme={null}
name: Deploy Agent from Custom Repo

on:
  workflow_dispatch:

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy agent
        uses: runloopai/deploy-agent@main
        with:
          api-key: ${{ secrets.RUNLOOP_API_KEY }}
          source-type: git
          git-repository: https://github.com/username/agent-repo
          git-ref: main
```

### Tar Archive Deployment

Package your agent files into a tar archive and deploy it.

```yaml theme={null}
name: Deploy Agent from Archive

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Create agent archive
        run: |
          tar -czf agent.tar.gz -C ./agent-code .
      
      - name: Deploy agent
        uses: runloopai/deploy-agent@main
        with:
          api-key: ${{ secrets.RUNLOOP_API_KEY }}
          source-type: tar
          path: agent.tar.gz
          object-ttl-days: 30
          setup-commands: |
            pip install -r requirements.txt
            chmod +x agent.py
```

### Tar Archive with Custom Build

Build your agent with custom steps, then deploy the resulting archive.

```yaml theme={null}
name: Build and Deploy Agent

on:
  push:
    branches: [main]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
      
      - name: Build agent
        run: |
          npm install
          npm run build
          tar -czf agent.tar.gz -C ./dist .
      
      - name: Deploy agent
        uses: runloopai/deploy-agent@main
        with:
          api-key: ${{ secrets.RUNLOOP_API_KEY }}
          source-type: tar
          path: agent.tar.gz
          agent-name: my-built-agent
```

### Single File Deployment

Deploy a single file as an agent.

```yaml theme={null}
name: Deploy Single File Agent

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Deploy agent
        uses: runloopai/deploy-agent@main
        with:
          api-key: ${{ secrets.RUNLOOP_API_KEY }}
          source-type: file
          path: ./scripts/agent.sh
          setup-commands: |
            chmod +x agent.sh
```

### npm Package Deployment

Deploy an agent from an npm package. Use `agent-version` to pin a specific package version.

```yaml theme={null}
name: Deploy npm Agent

on:
  workflow_dispatch:
    inputs:
      version:
        description: 'Package version'
        required: true

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy agent
        uses: runloopai/deploy-agent@main
        with:
          api-key: ${{ secrets.RUNLOOP_API_KEY }}
          source-type: npm
          agent-version: ${{ inputs.version }}  # Optional: pin package version
          agent-name: my-npm-agent
          npm-package: '@my-org/agent-package'
```

### pip Package Deployment

Deploy an agent from a PyPI package. Use `agent-version` to pin a specific package version.

```yaml theme={null}
name: Deploy pip Agent

on:
  workflow_dispatch:
    inputs:
      version:
        description: 'Package version'
        required: true

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy agent
        uses: runloopai/deploy-agent@main
        with:
          api-key: ${{ secrets.RUNLOOP_API_KEY }}
          source-type: pip
          agent-version: ${{ inputs.version }}  # Optional: pin package version
          agent-name: my-pip-agent
          pip-package: my-agent-package
```

## Best Practices

### Version Management

1. **Git agents**: Use `git-ref` to pin to a branch, tag, or tag. The `agent-version` field is not used.
2. **npm/pip agents**: Use `agent-version` to pin the installed package version (e.g., `2.1.123`). When omitted, the latest version from the registry is installed.
3. **Tar/file agents**: Each upload produces a new immutable object. The `agent-version` field is not used.

### Workflow Organization

1. **Separate build and deploy**: Create separate jobs for building and deploying
2. **Conditional deployment**: Only deploy on specific branches or tags
3. **Error handling**: Add error handling and notifications

```yaml theme={null}
name: Deploy Agent

on:
  push:
    branches: [main]
    tags:
      - 'v*'

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Deploy agent
        uses: runloopai/deploy-agent@main
        with:
          api-key: ${{ secrets.RUNLOOP_API_KEY }}
          source-type: git
      
      - name: Notify on failure
        if: failure()
        run: |
          echo "Deployment failed"
          # Add your notification logic here
```

### Security

1. **Never commit API keys**: Always use GitHub secrets
2. **Use environment-specific keys**: Use different API keys for different environments
3. **Prefer restricted keys**: Create keys with only the permissions your workflow needs to limit exposure if a key is compromised
4. **Limit secret access**: Use environment protection rules for production secrets

### Performance

1. **Cache dependencies**: Use GitHub Actions caching for faster builds
2. **Optimize archive size**: Only include necessary files in tar archives
3. **Use object TTL**: Set `object-ttl-days` for temporary deployments

## Troubleshooting

### Common Issues

**Deployment fails with authentication error**

* Verify your `RUNLOOP_API_KEY` secret is correctly set
* Check that the API key is valid and has the necessary permissions

**Agent creation fails**

* Verify the source repository/branch exists and is accessible
* Check that the tar archive or file path is correct
* For npm/pip sources, ensure `agent-version` is a valid package version string

**Setup commands fail**

* Verify the commands are valid for the agent's environment
* Check that required dependencies are available
* Review agent logs in the Runloop Dashboard

### Getting Help

* **GitHub Action Repository**: [runloopai/deploy-agent](https://github.com/runloopai/deploy-agent)
* **Runloop Documentation**: [Using the Agents API](/docs/devboxes/agents/using-agents-api)
* **Support**: [support@runloop.ai](mailto:support@runloop.ai)

## Related Documentation

* [Using the Agents API](/docs/devboxes/agents/using-agents-api) - Direct API usage with Python and TypeScript
* [Agent Mounts](/docs/devboxes/mounts/agent-mounts) - Mount agents to Devboxes
* [Storage Objects](/docs/storage-objects/overview) - Understanding object storage
