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

# Fix a GitHub issue

> Connect GitHub, give an agent write access to one repository, and run a session that fixes an issue and opens a pull request.

In this tutorial, an agent fixes a bug from a GitHub issue, adds a test, and opens a pull request. You then check the pull request and review it like any other. It takes about 20 minutes.

The examples use the repository `acme/web` and its issue 412; replace them with yours.

<Note>
  You need the Developer or Admin role in the organization; see [Organizations and roles](/recursion/organizations-and-roles). You also need permission to install a GitHub App on the GitHub account that owns the repository, or an existing GitHub connection in Recursion. The repository should run its tests on pull requests, for example in GitHub Actions, so you can see them pass on the agent's pull request.
</Note>

## Step 1: Connect GitHub

Connecting is an interactive authorization in GitHub, so do it in the console. It creates a connection for your organization but gives no agent access yet. Use the console or cURL.

<Tabs>
  <Tab title="Console">
    1. In the sidebar, click **Integrations**, then click **Add integration**.
    2. Choose **GitHub**, then click **Continue**.
    3. On GitHub, choose the account and select the repositories the connection may reach, including `acme/web`.
    4. Back in Recursion, choose the account if asked. The connection appears under **Integration connections**.
    5. Enable `issue_read`, `get_file_contents`, `create_branch`, `push_files`, and `create_pull_request` in the connection's tool selection. New connections start with read-only tools selected.
    6. Open the connection's actions menu and click **Test connection** to confirm it can issue a token.
  </Tab>

  <Tab title="cURL">
    Connect in the console first, then list connections to get the connection id you'll use in step 3.

    ```bash theme={"theme":"css-variables"}
    curl 'https://api.recursion.labelbox.com/managed-agents/v1/integrations/connections' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    ```
  </Tab>
</Tabs>

```json theme={"theme":"css-variables"}
{
  "connections": [
    {
      "connection_id": "31e6c9a4-2d75-48b0-a1f3-7c5e9d2b6a84",
      "organization_id": "org_01a08a705220724f9a2fe1bcd8638c9d",
      "provider": "github",
      "external_id": "58213377",
      "account_login": "acme",
      "account_type": "Organization",
      "resource_selection": "selected",
      "state": "active",
      "created_at": "2026-09-25T16:40:12Z",
      "updated_at": "2026-09-25T16:40:12Z"
    }
  ]
}
```

Continue when `state` is `active`.

## Step 2: Create an environment

The agent works on GitHub through its GitHub tools, which run outside the sandbox, so the environment needs no GitHub network rules. New environments block all outbound traffic, which is fine for this task.

<Tabs>
  <Tab title="Console">
    1. In the sidebar, click **Environments**, then click **Create environment**.
    2. Enter a **Name**, such as `github-fixes`.
    3. Click **Create environment**.
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X POST 'https://api.recursion.labelbox.com/managed-agents/v1/environments' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -H 'Content-Type: application/json' \
      -d '{
        "name": "github-fixes",
        "provider": "runs"
      }'
    ```
  </Tab>
</Tabs>

```json theme={"theme":"css-variables"}
{
  "organization_id": "org_01a08a705220724f9a2fe1bcd8638c9d",
  "environment_id": "9d3e7b52-1a4c-4f80-b6e9-2c8a5d0f7e13",
  "name": "github-fixes",
  "scope": "organization",
  "provider": "runs",
  "computer_use": false,
  "created_at": "2026-09-25T16:44:03Z",
  "updated_at": "2026-09-25T16:44:03Z"
}
```

See [Environments](/recursion/environments).

## Step 3: Create the agent with GitHub access

Give the agent the GitHub tools it needs and access to only the repository it needs. The selected tools determine its short-lived token permissions. GitHub's MCP tools run outside the sandbox; `git` and `gh` in the sandbox are not authenticated for GitHub.

<Tabs>
  <Tab title="Console">
    1. In the sidebar, click **Agents**, then click **Create agent** and choose **Blank**.
    2. Enter a **Name**, choose a model, and paste the `system` value from the cURL tab into **System prompt**. Click **Create agent**.
    3. On the agent's **Configuration** tab, under **Integrations**, click **Add integration access** and select the GitHub connection.
    4. Select `issue_read`, `get_file_contents`, `create_branch`, `push_files`, and `create_pull_request` under **Tools**.
    5. Clear **All authorized repositories**, then select `acme/web`.
    6. Click **Use this access**, then click **Save new version**.
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X POST 'https://api.recursion.labelbox.com/managed-agents/v1/agents' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -H 'Content-Type: application/json' \
      -d '{
        "name": "Issue fixer",
        "model": "<model-id>",
        "system": "You fix GitHub issues with your GitHub tools.\nRead the issue and the code it touches, then find the cause of the bug.\nOn a new branch named fix/issue-<number>, commit the fix and a test that fails without it.\nOpen a pull request whose description starts with \"Fixes\" and the issue URL. Never commit to main.\nEnd with the pull request URL.",
        "nativeIntegrations": [
          {
            "connectionId": "31e6c9a4-2d75-48b0-a1f3-7c5e9d2b6a84",
            "permission": "write",
            "tools": ["issue_read", "get_file_contents", "create_branch", "push_files", "create_pull_request"],
            "resources": ["acme/web"]
          }
        ]
      }'
    ```
  </Tab>
</Tabs>

```json theme={"theme":"css-variables"}
{
  "agent_id": "5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55",
  "latest_agent_version_id": "c1a94e07-2f6b-4d18-b3a5-0e7d8c6f4a21",
  "name": "Issue fixer",
  "nativeIntegrations": [
    {
      "connectionId": "31e6c9a4-2d75-48b0-a1f3-7c5e9d2b6a84",
      "permission": "write",
      "resources": ["acme/web"]
    }
  ]
}
```

You can grant GitHub through a vault instead, which is useful when several agents share one grant. See [GitHub](/recursion/github) and [Vaults](/recursion/vaults).

## Step 4: Start the session

The opening message names the issue. The system prompt already says how to work: find the cause, commit the fix and a test on a new branch, and open a pull request.

<Tabs>
  <Tab title="Console">
    1. In the sidebar, click **Sessions**, then click **Launch session**.
    2. Choose the **Issue fixer** agent and the **github-fixes** environment.
    3. In **Opening message**, enter `Fix https://github.com/acme/web/issues/412 and open a pull request.`
    4. Click **Launch session**.
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X POST 'https://api.recursion.labelbox.com/managed-agents/v1/sessions' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -H 'Idempotency-Key: acme-web-issue-412' \
      -H 'Content-Type: application/json' \
      -d '{
        "agent_id": "5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55",
        "environment_id": "9d3e7b52-1a4c-4f80-b6e9-2c8a5d0f7e13",
        "message": "Fix https://github.com/acme/web/issues/412 and open a pull request."
      }'
    ```
  </Tab>
</Tabs>

The API answers `202 Accepted`.

```json theme={"theme":"css-variables"}
{
  "session_id": "b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38",
  "status_path": "/managed-agents/v1/sessions/b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38"
}
```

The `Idempotency-Key` makes the start safe to retry: sending the same key again returns the same session instead of starting a second one.

## Step 5: Wait for the session to finish

Watch the session in the console, or poll it until the agent's turn ends.

<Tabs>
  <Tab title="Console">
    1. In the sidebar, click **Sessions**, then open the session.
    2. Follow the transcript as the agent reads the issue and code, commits, and opens the pull request.
    3. When the agent is done, its last message gives the pull request URL.
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl 'https://api.recursion.labelbox.com/managed-agents/v1/sessions/b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    ```
  </Tab>
</Tabs>

A finished session looks like this. Some fields are left out here.

```json theme={"theme":"css-variables"}
{
  "session_id": "b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38",
  "status": "completed",
  "execution_state": "idle",
  "stop_reason": "end_turn",
  "updated_at": "2026-09-25T17:09:51Z"
}
```

### What success means

* The session's `stop_reason` is `end_turn`, and the agent's last message gives the pull request URL.
* A pull request is open in `acme/web` from a branch other than `main`, its description starts with "Fixes" and the issue URL, and it adds a test for the bug.
* A finished session doesn't prove the work is right. Check the pull request and its checks before you merge. See [What success means](/recursion/sessions#what-success-means) for other session states.

## Step 6: Review the pull request

Open the URL from the agent's last message, or list the repository's open pull requests through the connection.

```bash theme={"theme":"css-variables"}
curl 'https://api.recursion.labelbox.com/managed-agents/v1/integrations/connections/31e6c9a4-2d75-48b0-a1f3-7c5e9d2b6a84/repositories/acme/web/pull-requests?state=open' \
  -H "Authorization: Bearer $RECURSION_API_KEY"
```

```json theme={"theme":"css-variables"}
{
  "page": 1,
  "pull_requests": [
    {
      "number": 418,
      "title": "Escape quotes in search queries",
      "head_sha": "3f9c2e7a1b4d6e8f0a2c4e6b8d0f1a3c5e7b9d2f",
      "draft": false
    }
  ]
}
```

Review and merge it the way you would any contributor's pull request.

## What can go wrong

| Symptom | Cause | Fix |
| - | - | - |
| The agent has no GitHub tools | The agent version has no GitHub access, or the session started from an older version. | Add integration access, save a new version, and start a new session. |
| The repository returns `404` | The GitHub App installation or the grant's repository list doesn't include `acme/web`. | Add the repository in GitHub and in the agent's integration access. |
| Creating a branch or pull request is refused | The connection or agent lacks `create_branch`, `push_files`, or `create_pull_request`. | Enable those tools on the GitHub connection, then select them for the agent. |
| The pull request's checks fail | The fix or its test is wrong. | Send a follow-up message with the failing check, and ask the agent to update the branch. |
| The agent stopped before opening a pull request | It hit a problem it couldn't solve. | Read its last message, then send a follow-up message with what to do next. |
| The agent committed to the wrong branch | The system prompt didn't forbid it strongly enough. | Keep "Never commit to main" in the system prompt, and protect `main` in GitHub. |

## Limits

* A grant can list up to 500 repositories.
* An agent can hold up to 25 integration connections.
* See [Limits](/recursion/limits) for session and environment limits.

## Next steps

<CardGroup cols={2}>
  <Card title="GitHub" href="/recursion/github">
    Permission presets, vault grants, and how GitHub tools work.
  </Card>

  <Card title="Automations" href="/recursion/automations">
    Start this agent when an issue is labeled.
  </Card>

  <Card title="Research team tutorial" href="/recursion/use-cases/research-team">
    Split a larger task across a team.
  </Card>

  <Card title="Environments" href="/recursion/environments">
    Network policy, setup scripts, and compute.
  </Card>
</CardGroup>
