GitHub 접근하기

GitHub 접근하기 (Accessing GitHub)

GitHub 저장소를 세션 샌드박스에 마운트하고 GitHub MCP에 연결하면, 에이전트가 저장소를 복제하고 읽으며 풀 리퀘스트까지 만들 수 있어요. GitHub 저장소는 캐시되므로 같은 저장소를 쓰는 이후 세션은 더 빨리 시작된답니다.

출처: 문서

본문

GitHub 저장소를 세션 샌드박스에 마운트하고 GitHub MCP에 연결해 풀 리퀘스트를 만들 수 있어요.

GitHub 저장소는 캐시되므로, 같은 저장소를 사용하는 이후 세션은 더 빨리 시작돼요.

GitHub MCP and session resources

먼저 GitHub MCP 서버를 선언하는 에이전트를 만들어요. 에이전트 정의는 서버 URL만 담고 인증 토큰은 담지 않아요:

```bash cURL agent_id=$(curl -fsS https://api.anthropic.com/v1/agents \ -H "x-api-key: $ANTHR...KEY" \ -H "anthropic-version: 2023-06-01" \ -H "anthropic-beta: managed-agents-2026-04-01" \ -H "content-type: application/json" \ --data @- < ```bash CLI ant apply code-reviewer.md ```
<File filename="code-reviewer.md">
  ```markdown
  ---
  name: Code Reviewer
  model: claude-opus-5-5
  mcp_servers:
    - type: url
      name: github
      url: https://api.githubcopilot.com/mcp/
  tools:
    - type: agent_toolset_20260401
    - type: mcp_toolset
      mcp_server_name: github
  ---

  You are a code review assistant with access to GitHub.
  ```
</File>
agent = client.beta.agents.create(
    name="Code Reviewer",
    model="claude-opus-5-5",
    system="You are a code review assistant with access to GitHub.",
    mcp_servers=[
        {
            "type": "url",
            "name": "github",
            "url": "https://api.githubcopilot.com/mcp/",
        },
    ],
    tools=[
        {"type": "agent_toolset_20260401"},
        {
            "type": "mcp_toolset",
            "mcp_server_name": "github",
        },
    ],
)
const agent = await client.beta.agents.create({
  name: "Code Reviewer",
  model: "claude-opus-5-5",
  system: "You are a code review assistant with access to GitHub.",
  mcp_servers: [
    {
      type: "url",
      name: "github",
      url: "https://api.githubcopilot.com/mcp/",
    },
  ],
  tools: [
    { type: "agent_toolset_20260401" },
    {
      type: "mcp_toolset",
      mcp_server_name: "github",
    },
  ],
});
var agent = await client.Beta.Agents.Create(new()
{
    Name = "Code Reviewer",
    Model = BetaManagedAgentsModel.ClaudeOpus5_5,
    System = "You are a code review assistant with access to GitHub.",
    McpServers =
    [
        new() { Type = "url", Name = "github", Url = "https://api.githubcopilot.com/mcp/" },
    ],
    Tools =
    [
        new BetaManagedAgentsAgentToolset20260401Params
        {
            Type = "agent_toolset_20260401",
        },
        new BetaManagedAgentsMcpToolsetParams
        {
            Type = "mcp_toolset",
            McpServerName = "github",
        },
    ],
});
agent, err := client.Beta.Agents.New(ctx, anthropic.BetaAgentNewParams{
	Name: "Code Reviewer",
	Model: anthropic.BetaManagedAgentsModelConfigParams{
		ID: anthropic.BetaManagedAgentsModelClaudeOpus5_5,
	},
	System: anthropic.String("You are a code review assistant with access to GitHub."),
	MCPServers: []anthropic.BetaManagedAgentsURLMCPServerParams{
		{
			Type: anthropic.BetaManagedAgentsURLMCPServerParamsTypeURL,
			Name: "github",
			URL:  "https://api.githubcopilot.com/mcp/",
		},
	},
	Tools: []anthropic.BetaAgentNewParamsToolUnion{
		{
			OfAgentToolset20260401: &anthropic.BetaManagedAgentsAgentToolset20260401Params{
				Type: anthropic.BetaManagedAgentsAgentToolset20260401ParamsTypeAgentToolset20260401,
			},
		},
		{
			OfMCPToolset: &anthropic.BetaManagedAgentsMCPToolsetParams{
				Type:          anthropic.BetaManagedAgentsMCPToolsetParamsTypeMCPToolset,
				MCPServerName: "github",
			},
		},
	},
})
if err != nil {
	panic(err)
}
var agent = client.beta().agents().create(AgentCreateParams.builder()
    .name("Code Reviewer")
    .model(BetaManagedAgentsModel.CLAUDE_OPUS_5_5)
    .system("You are a code review assistant with access to GitHub.")
    .addMcpServer(BetaManagedAgentsUrlMcpServerParams.builder()
        .type(BetaManagedAgentsUrlMcpServerParams.Type.URL)
        .name("github")
        .url("https://api.githubcopilot.com/mcp/")
        .build())
    .addTool(BetaManagedAgentsAgentToolset20260401Params.builder()
        .type(BetaManagedAgentsAgentToolset20260401Params.Type.AGENT_TOOLSET_20260401)
        .build())
    .addTool(BetaManagedAgentsMcpToolsetParams.builder()
        .type(BetaManagedAgentsMcpToolsetParams.Type.MCP_TOOLSET)
        .mcpServerName("github")
        .build())
    .build());
$agent = $client->beta->agents->create(
    name: 'Code Reviewer',
    model: 'claude-opus-5-5',
    system: 'You are a code review assistant with access to GitHub.',
    mcpServers: [
        [
            'type' => 'url',
            'name' => 'github',
            'url' => 'https://api.githubcopilot.com/mcp/',
        ],
    ],
    tools: [
        ['type' => 'agent_toolset_20260401'],
        [
            'type' => 'mcp_toolset',
            'mcpServerName' => 'github',
        ],
    ],
);
agent = client.beta.agents.create(
  name: "Code Reviewer",
  model: "claude-opus-5-5",
  system_: "You are a code review assistant with access to GitHub.",
  mcp_servers: [
    {
      type: "url",
      name: "github",
      url: "https://api.githubcopilot.com/mcp/"
    }
  ],
  tools: [
    {type: "agent_toolset_20260401"},
    {
      type: "mcp_toolset",
      mcp_server_name: "github"
    }
  ]
)

그런 다음 GitHub 저장소를 마운트하는 세션을 만들어요:

```bash cURL session_id=$(curl -fsS https://api.anthropic.com/v1/sessions \ -H "x-api-key: $ANTHR...KEY" \ -H "anthropic-version: 2023-06-01" \ -H "anthropic-beta: managed-agents-2026-04-01" \ -H "content-type: application/json" \ --data @- <SESSION_ID=$(ant beta:sessions create \ --agent "$AGENT_ID" \ --environment-id "$ENVIRONMENT_ID" \ --transform id --raw-output <<'EOF' resources: - type: github_repository url: https://github.com/org/repo mount_path: /workspace/repo authorization_token: ghp_your_github_token EOF )
session = client.beta.sessions.create(
    agent=agent.id,
    environment_id=environment.id,
    resources=[
        {
            "type": "github_repository",
            "url": "https://github.com/org/repo",
            "mount_path": "/workspace/repo",
            "authorization_token": "ghp_your_github_token",
        },
    ],
)
const session = await client.beta.sessions.create({
  agent: agent.id,
  environment_id: environment.id,
  resources: [
    {
      type: "github_repository",
      url: "https://github.com/org/repo",
      mount_path: "/workspace/repo",
      authorization_token: "ghp_your_github_token",
    },
  ],
});
var session = await client.Beta.Sessions.Create(new()
{
    Agent = agent.ID,
    EnvironmentID = environment.ID,
    Resources =
    [
        new BetaManagedAgentsGitHubRepositoryResourceParams
        {
            Type = "github_repository",
            Url = "https://github.com/org/repo",
            MountPath = "/workspace/repo",
            AuthorizationToken = "ghp_your_github_token",
        },
    ],
});
session, err := client.Beta.Sessions.New(ctx, anthropic.BetaSessionNewParams{
	Agent:         anthropic.BetaSessionNewParamsAgentUnion{OfString: anthropic.String(agent.ID)},
	EnvironmentID: environment.ID,
	Resources: []anthropic.BetaSessionNewParamsResourceUnion{
		{
			OfGitHubRepository: &anthropic.BetaManagedAgentsGitHubRepositoryResourceParams{
				Type:               anthropic.BetaManagedAgentsGitHubRepositoryResourceParamsTypeGitHubRepository,
				URL:                "https://github.com/org/repo",
				MountPath:          anthropic.String("/workspace/repo"),
				AuthorizationToken: "ghp_your_github_token",
			},
		},
	},
})
if err != nil {
	panic(err)
}
var session = client.beta().sessions().create(SessionCreateParams.builder()
    .agent(agent.id())
    .environmentId(environment.id())
    .addResource(BetaManagedAgentsGitHubRepositoryResourceParams.builder()
        .type(BetaManagedAgentsGitHubRepositoryResourceParams.Type.GITHUB_REPOSITORY)
        .url("https://github.com/org/repo")
        .mountPath("/workspace/repo")
        .authorizationToken("ghp_your_github_token")
        .build())
    .build());
$session = $client->beta->sessions->create(
    agent: $agent->id,
    environmentID: $environment->id,
    resources: [
        [
            'type' => 'github_repository',
            'url' => 'https://github.com/org/repo',
            'mountPath' => '/workspace/repo',
            'authorizationToken' => 'ghp_your_github_token',
        ],
    ],
);
session = client.beta.sessions.create(
  agent: agent.id,
  environment_id: environment.id,
  resources: [
    {
      type: "github_repository",
      url: "https://github.com/org/repo",
      mount_path: "/workspace/repo",
      authorization_token: "ghp_your_github_token"
    }
  ]
)

github_repository 리소스는 다음 필드를 받아요:

Field Description
type Required. Must be "github_repository".
url Required. The repository's HTTPS URL in the form https://github.com/<owner>/<repo>, without a .git suffix. Other forms, including SSH URLs, are rejected with an invalid_request_error.
authorization_token Required. The GitHub token used to clone the repository. It is not echoed in API responses. See Token permissions.
mount_path Optional. The directory under /workspace to clone the repository into. Defaults to /workspace/<repo-name>.
checkout Optional. A branch ({"type": "branch", "name": "main"}) or commit ({"type": "commit", "sha": "..."}) to check out. Defaults to the repository's default branch.

저장소를 마운트하면 루트 .claude/skills 디렉터리에 저장된 모든 스킬도 불러와져요. 스킬은 세션당 한 번, 세션 시작 시 체크아웃된 저장소 상태에서 발견돼요. 자세한 내용은 Load skills from a GitHub repository를 참고하세요.

Token permissions

GitHub 토큰을 제공할 때는 최소한의 필요한 권한을 사용하세요:

Action Required scopes
Clone private repos repo
Create PRs repo
Read issues repo (private) or public_repo
Create issues repo (private) or public_repo
Use fine-grained personal access tokens with minimum required permissions. Avoid using tokens with broad access to your GitHub account.

Multiple repositories

resources 배열에 항목을 추가해 여러 저장소를 마운트하세요:

```bash cURL resources='[ { "type": "github_repository", "url": "https://github.com/org/frontend", "mount_path": "/workspace/frontend", "authorization_token": "ghp_your_github_token" }, { "type": "github_repository", "url": "https://github.com/org/backend", "mount_path": "/workspace/backend", "authorization_token": "ghp_your_github_token" } ]' ```
RESOURCES_BODY=$(cat <<'EOF'
resources:
  - type: github_repository
    url: https://github.com/org/frontend
    mount_path: /workspace/frontend
    authorization_token: ghp_your_github_token
  - type: github_repository
    url: https://github.com/org/backend
    mount_path: /workspace/backend
    authorization_token: ghp_your_github_token
EOF
)
resources = [
    {
        "type": "github_repository",
        "url": "https://github.com/org/frontend",
        "mount_path": "/workspace/frontend",
        "authorization_token": "ghp_your_github_token",
    },
    {
        "type": "github_repository",
        "url": "https://github.com/org/backend",
        "mount_path": "/workspace/backend",
        "authorization_token": "ghp_your_github_token",
    },
]
const resources = [
  {
    type: "github_repository",
    url: "https://github.com/org/frontend",
    mount_path: "/workspace/frontend",
    authorization_token: "ghp_your_github_token",
  },
  {
    type: "github_repository",
    url: "https://github.com/org/backend",
    mount_path: "/workspace/backend",
    authorization_token: "ghp_your_github_token",
  },
];
BetaManagedAgentsGitHubRepositoryResourceParams[] resources =
[
    new()
    {
        Type = "github_repository",
        Url = "https://github.com/org/frontend",
        MountPath = "/workspace/frontend",
        AuthorizationToken = "ghp_your_github_token",
    },
    new()
    {
        Type = "github_repository",
        Url = "https://github.com/org/backend",
        MountPath = "/workspace/backend",
        AuthorizationToken = "ghp_your_github_token",
    },
];
resources := []anthropic.BetaSessionNewParamsResourceUnion{
	{
		OfGitHubRepository: &anthropic.BetaManagedAgentsGitHubRepositoryResourceParams{
			Type:               anthropic.BetaManagedAgentsGitHubRepositoryResourceParamsTypeGitHubRepository,
			URL:                "https://github.com/org/frontend",
			MountPath:          anthropic.String("/workspace/frontend"),
			AuthorizationToken: "ghp_your_github_token",
		},
	},
	{
		OfGitHubRepository: &anthropic.BetaManagedAgentsGitHubRepositoryResourceParams{
			Type:               anthropic.BetaManagedAgentsGitHubRepositoryResourceParamsTypeGitHubRepository,
			URL:                "https://github.com/org/backend",
			MountPath:          anthropic.String("/workspace/backend"),
			AuthorizationToken: "ghp_your_github_token",
		},
	},
}
var resources = List.of(
    BetaManagedAgentsGitHubRepositoryResourceParams.builder()
        .type(BetaManagedAgentsGitHubRepositoryResourceParams.Type.GITHUB_REPOSITORY)
        .url("https://github.com/org/frontend")
        .mountPath("/workspace/frontend")
        .authorizationToken("ghp_your_github_token")
        .build(),
    BetaManagedAgentsGitHubRepositoryResourceParams.builder()
        .type(BetaManagedAgentsGitHubRepositoryResourceParams.Type.GITHUB_REPOSITORY)
        .url("https://github.com/org/backend")
        .mountPath("/workspace/backend")
        .authorizationToken("ghp_your_github_token")
        .build());
$resources = [
    [
        'type' => 'github_repository',
        'url' => 'https://github.com/org/frontend',
        'mountPath' => '/workspace/frontend',
        'authorizationToken' => 'ghp_your_github_token',
    ],
    [
        'type' => 'github_repository',
        'url' => 'https://github.com/org/backend',
        'mountPath' => '/workspace/backend',
        'authorizationToken' => 'ghp_your_github_token',
    ],
];
resources = [
  {
    type: "github_repository",
    url: "https://github.com/org/frontend",
    mount_path: "/workspace/frontend",
    authorization_token: "ghp_your_github_token"
  },
  {
    type: "github_repository",
    url: "https://github.com/org/backend",
    mount_path: "/workspace/backend",
    authorization_token: "ghp_your_github_token"
  }
]

Managing repositories on a running session

세션이 만들어진 후에는 저장소 리소스를 나열하고 인증 토큰을 회전(rotate)시킬 수 있어요. 각 리소스는 세션 생성 시(또는 resources.list를 통해) 반환되는 id를 가지며, 업데이트에 사용해요. 저장소는 세션 수명 동안 붙어 있어요. 마운트된 저장소를 바꾸려면 새 세션을 만들어야 해요.

```bash cURL # List resources on the session repo_resource_id=$(curl -fsS "https://api.anthropic.com/v1/sessions/$session_id/resources" \ -H "x-api-key: $ANTHR...KEY" \ -H "anthropic-version: 2023-06-01" \ -H "anthropic-beta: managed-agents-2026-04-01" \ -H "content-type: application/json" | jq -r '.data[0].id') echo "$repo_resource_id" # "sesrsc_01ABC..."

Rotate the authorization token

curl -fsS "https://api.anthropic.com/v1/sessions/$session_id/resources/$repo_resource_id" \

...

-o /dev/null \
--data @- <<JSON

{ "authorization_token": "ghp_your_new_github_token" } JSON


```bash CLI
# List resources on the session
ant beta:sessions:resources list --session-id "$SESSION_ID"

# Rotate the authorization token on a specific resource
ant beta:sessions:resources update \
  --session-id "$SESSION_ID" \
  --resource-id "$RESOURCE_ID" \
  --authorization-token "ghp_your_new_github_token"
# List resources on the session
listed = client.beta.sessions.resources.list(session.id)
repo_resource_id = listed.data[0].id
print(repo_resource_id)  # "sesrsc_01ABC..."

# Rotate the authorization token
client.beta.sessions.resources.update(
    repo_resource_id,
    session_id=session.id,
    authorization_token="ghp_your_new_github_token",
)
// List resources on the session
const listed = await client.beta.sessions.resources.list(session.id);
const repoResource = listed.data.find(
  (entry) => entry.type === "github_repository",
);
if (!repoResource) {
  throw new Error("No GitHub repository resource on the session");
}
const repoResourceId = repoResource.id;
console.log(repoResourceId); // "sesrsc_01ABC..."

// Rotate the authorization token
await client.beta.sessions.resources.update(repoResourceId, {
  session_id: session.id,
  authorization_token: "ghp_your_new_github_token",
});
// List resources on the session
var listed = await client.Beta.Sessions.Resources.List(session.ID);
var repoResourceId = (await listed.Paginate().FirstAsync()).ID;
Console.WriteLine(repoResourceId); // "sesrsc_01ABC..."

// Rotate the authorization token
await client.Beta.Sessions.Resources.Update(repoResourceId, new()
{
    SessionID = session.ID,
    AuthorizationToken = "ghp_your_new_github_token",
});
// List resources on the session
listed, err := client.Beta.Sessions.Resources.List(ctx, session.ID, anthropic.BetaSessionResourceListParams{})
if err != nil {
	panic(err)
}
repoResourceID := listed.Data[0].ID
fmt.Println(repoResourceID) // "sesrsc_01ABC..."

// Rotate the authorization token
_, err = client.Beta.Sessions.Resources.Update(ctx, repoResourceID, anthropic.BetaSessionResourceUpdateParams{
	SessionID:          session.ID,
	AuthorizationToken: "ghp_your_new_github_token",
})
if err != nil {
	panic(err)
}
// List resources on the session
var listed = client.beta().sessions().resources().list(session.id());
var repoResourceId = listed.data().getFirst().asGitHubRepository().id();
IO.println(repoResourceId);  // "sesrsc_01ABC..."

// Rotate the authorization token
client.beta().sessions().resources().update(repoResourceId, ResourceUpdateParams.builder()
    .sessionId(session.id())
    .authorizationToken("ghp_your_new_github_token")
    .build());
// List resources on the session
$listed = $client->beta->sessions->resources->list($session->id);
$repoResourceId = $listed->data[0]->id;
echo $repoResourceId, PHP_EOL; // "sesrsc_01ABC..."

// Rotate the authorization token
$client->beta->sessions->resources->update(
    $repoResourceId,
    sessionID: $session->id,
    authorizationToken: 'ghp_your_new_github_token',
);
# List resources on the session
listed = client.beta.sessions.resources.list(session.id)
repo_resource_id = listed.data.first.id
puts repo_resource_id # "sesrsc_01ABC..."

# Rotate the authorization token
client.beta.sessions.resources.update(
  repo_resource_id,
  session_id: session.id,
  authorization_token: "ghp_your_new_github_token"
)

Creating pull requests

GitHub MCP 서버를 사용하면 에이전트가 브랜치를 만들고, 변경사항을 커밋하고, 푸시할 수 있어요:

```bash cURL curl -fsS "https://api.anthropic.com/v1/sessions/$session_id/events" \ -H "x-api-key: $ANTHR...KEY" \ -H "anthropic-version: 2023-06-01" \ -H "anthropic-beta: managed-agents-2026-04-01" \ -H "content-type: application/json" \ -o /dev/null \ --data @- <ant beta:sessions:events send --session-id "$SESSION_ID" > /dev/null <<'EOF' events: - type: user.message content: - type: text text: Fix the type error in src/utils.ts, commit it to a new branch, and push it. EOF
client.beta.sessions.events.send(
    session.id,
    events=[
        {
            "type": "user.message",
            "content": [
                {
                    "type": "text",
                    "text": "Fix the type error in src/utils.ts, commit it to a new branch, and push it.",
                },
            ],
        },
    ],
)
await client.beta.sessions.events.send(session.id, {
  events: [
    {
      type: "user.message",
      content: [
        {
          type: "text",
          text: "Fix the type error in src/utils.ts, commit it to a new branch, and push it.",
        },
      ],
    },
  ],
});
await client.Beta.Sessions.Events.Send(session.ID, new()
{
    Events =
    [
        new BetaManagedAgentsUserMessageEventParams
        {
            Type = "user.message",
            Content =
            [
                new BetaManagedAgentsTextBlock
                {
                    Type = "text",
                    Text = "Fix the type error in src/utils.ts, commit it to a new branch, and push it.",
                },
            ],
        },
    ],
});
_, err = client.Beta.Sessions.Events.Send(ctx, session.ID, anthropic.BetaSessionEventSendParams{
	Events: []anthropic.BetaManagedAgentsEventParamsUnion{
		{
			OfUserMessage: &anthropic.BetaManagedAgentsUserMessageEventParams{
				Type: anthropic.BetaManagedAgentsUserMessageEventParamsTypeUserMessage,
				Content: []anthropic.BetaManagedAgentsUserMessageEventParamsContentUnion{
					{
						OfText: &anthropic.BetaManagedAgentsTextBlockParam{
							Type: anthropic.BetaManagedAgentsTextBlockTypeText,
							Text: "Fix the type error in src/utils.ts, commit it to a new branch, and push it.",
						},
					},
				},
			},
		},
	},
})
if err != nil {
	panic(err)
}
client.beta().sessions().events().send(session.id(), EventSendParams.builder()
    .addEvent(BetaManagedAgentsUserMessageEventParams.builder()
        .type(BetaManagedAgentsUserMessageEventParams.Type.USER_MESSAGE)
        .addContent(BetaManagedAgentsTextBlock.builder()
            .type(BetaManagedAgentsTextBlock.Type.TEXT)
            .text("Fix the type error in src/utils.ts, commit it to a new branch, and push it.")
            .build())
        .build())
    .build());
$client->beta->sessions->events->send(
    $session->id,
    events: [
        [
            'type' => 'user.message',
            'content' => [
                [
                    'type' => 'text',
                    'text' => 'Fix the type error in src/utils.ts, commit it to a new branch, and push it.',
                ],
            ],
        ],
    ],
);
client.beta.sessions.events.send_(
  session.id,
  events: [
    {
      type: "user.message",
      content: [
        {
          type: "text",
          text: "Fix the type error in src/utils.ts, commit it to a new branch, and push it."
        }
      ]
    }
  ]
)

Next steps

Stream events and steer the agent while it opens the pull request Connect more MCP servers to give the agent additional tools Mount files in the sandbox alongside your repositories

더 알아보기 (Learn more)