- 파일 첨부 파일 (
type: "file"): 절대 경로를 제공하고, 런타임은 디스크에서 파일을 읽고, base64로 변환하고, LLM으로 보냅니다. - Blob 첨부 파일 (
type: "blob"): base64로 인코딩된 데이터를 직접 제공합니다. 이미지가 이미 메모리에 있을 때 유용합니다(예: 스크린샷, 생성된 이미지 또는 API의 데이터).
Overview

| Concept | Description |
|---|---|
| 파일 첨부 | 디스크의 이미지에 대한 type: "file" 첨부 파일 및 path 절대 경로 |
| Blob 파일 첨부 | base64로 인코딩된 type: "blob"첨부 파일 및 data디스크 I/O가 필요하지 않은 첨부 파일 mimeType |
| 자동 인코딩 | 파일 첨부 파일의 경우 런타임은 이미지를 읽고 자동으로 base64로 변환합니다. |
| 자동 크기 조정 | 런타임은 모델별 제한을 초과하는 이미지의 크기를 자동으로 조정하거나 품질을 줄입니다. |
| 비전 기능 | 모델은 이미지를 처리하기 위해 capabilities.supports.vision = true가 필요합니다. |
빠른 시작 - 파일 첨부
파일 첨부 파일 형식을 사용하여 모든 메시지에 이미지 파일을 첨부합니다. 경로는 디스크의 이미지에 대한 절대 경로여야 합니다.
import { CopilotClient } from "@github/copilot-sdk";
const client = new CopilotClient();
await client.start();
const session = await client.createSession({
model: "gpt-4.1",
onPermissionRequest: async () => ({ kind: "approve-once" }),
});
await session.send({
prompt: "Describe what you see in this image",
attachments: [
{
type: "file",
path: "/absolute/path/to/screenshot.png",
},
],
});
from copilot import CopilotClient, PermissionDecisionApproveOnce
client = CopilotClient()
await client.start()
session = await client.create_session(
on_permission_request=lambda req, inv: PermissionDecisionApproveOnce(),
model="gpt-4.1",
)
await session.send(
"Describe what you see in this image",
attachments=[
{
"type": "file",
"path": "/absolute/path/to/screenshot.png",
},
],
)
package main
import (
"context"
copilot "github.com/github/copilot-sdk/go"
"github.com/github/copilot-sdk/go/rpc"
)
func main() {
ctx := context.Background()
client := copilot.NewClient(nil)
client.Start(ctx)
session, _ := client.CreateSession(ctx, &copilot.SessionConfig{
Model: "gpt-4.1",
OnPermissionRequest: func(req copilot.PermissionRequest, inv copilot.PermissionInvocation) (rpc.PermissionDecision, error) {
return &rpc.PermissionDecisionApproveOnce{}, nil
},
})
path := "/absolute/path/to/screenshot.png"
session.Send(ctx, copilot.MessageOptions{
Prompt: "Describe what you see in this image",
Attachments: []copilot.Attachment{
&copilot.UserMessageAttachmentFile{
DisplayName: "screenshot.png",
Path: path,
},
},
})
}
ctx := context.Background()
client := copilot.NewClient(nil)
client.Start(ctx)
session, _ := client.CreateSession(ctx, &copilot.SessionConfig{
Model: "gpt-4.1",
OnPermissionRequest: func(req copilot.PermissionRequest, inv copilot.PermissionInvocation) (rpc.PermissionDecision, error) {
return &rpc.PermissionDecisionApproveOnce{}, nil
},
})
path := "/absolute/path/to/screenshot.png"
session.Send(ctx, copilot.MessageOptions{
Prompt: "Describe what you see in this image",
Attachments: []copilot.Attachment{
&copilot.UserMessageAttachmentFile{
DisplayName: "screenshot.png",
Path: path,
},
},
})
using GitHub.Copilot;
using GitHub.Copilot.Rpc;
public static class ImageInputExample
{
public static async Task Main()
{
await using var client = new CopilotClient();
await using var session = await client.CreateSessionAsync(new SessionConfig
{
Model = "gpt-4.1",
OnPermissionRequest = (req, inv) =>
Task.FromResult(PermissionDecision.ApproveOnce()),
});
await session.SendAsync(new MessageOptions
{
Prompt = "Describe what you see in this image",
Attachments = new List<UserMessageAttachment>
{
new UserMessageAttachmentFile
{
Path = "/absolute/path/to/screenshot.png",
DisplayName = "screenshot.png",
},
},
});
}
}
using GitHub.Copilot;
using GitHub.Copilot.Rpc;
await using var client = new CopilotClient();
await using var session = await client.CreateSessionAsync(new SessionConfig
{
Model = "gpt-4.1",
OnPermissionRequest = (req, inv) =>
Task.FromResult(PermissionDecision.ApproveOnce()),
});
await session.SendAsync(new MessageOptions
{
Prompt = "Describe what you see in this image",
Attachments = new List<UserMessageAttachment>
{
new UserMessageAttachmentFile
{
Path = "/absolute/path/to/screenshot.png",
DisplayName = "screenshot.png",
},
},
});
import com.github.copilot.sdk.CopilotClient;
import com.github.copilot.sdk.events.*;
import com.github.copilot.sdk.json.*;
import java.util.List;
try (var client = new CopilotClient()) {
client.start().get();
var session = client.createSession(
new SessionConfig()
.setModel("gpt-4.1")
.setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
).get();
session.send(new MessageOptions()
.setPrompt("Describe what you see in this image")
.setAttachments(List.of(
new Attachment("file", "/absolute/path/to/screenshot.png", "screenshot.png")
))
).get();
}
빠른 시작 - Blob 첨부 파일
이미 메모리에 이미지 데이터가 있는 경우(예: 앱에서 캡처한 스크린샷 또는 API에서 가져온 이미지) Blob 첨부 파일을 사용하여 디스크에 쓰지 않고 직접 보냅니다.
import { CopilotClient } from "@github/copilot-sdk";
const client = new CopilotClient();
await client.start();
const session = await client.createSession({
model: "gpt-4.1",
onPermissionRequest: async () => ({ kind: "approve-once" }),
});
const base64ImageData = "..."; // your base64-encoded image
await session.send({
prompt: "Describe what you see in this image",
attachments: [
{
type: "blob",
data: base64ImageData,
mimeType: "image/png",
displayName: "screenshot.png",
},
],
});
from copilot import CopilotClient, PermissionDecisionApproveOnce
client = CopilotClient()
await client.start()
session = await client.create_session(
on_permission_request=lambda req, inv: PermissionDecisionApproveOnce(),
model="gpt-4.1",
)
base64_image_data = "..." # your base64-encoded image
await session.send(
"Describe what you see in this image",
attachments=[
{
"type": "blob",
"data": base64_image_data,
"mimeType": "image/png",
"displayName": "screenshot.png",
},
],
)
package main
import (
"context"
copilot "github.com/github/copilot-sdk/go"
"github.com/github/copilot-sdk/go/rpc"
)
func main() {
ctx := context.Background()
client := copilot.NewClient(nil)
client.Start(ctx)
session, _ := client.CreateSession(ctx, &copilot.SessionConfig{
Model: "gpt-4.1",
OnPermissionRequest: func(req copilot.PermissionRequest, inv copilot.PermissionInvocation) (rpc.PermissionDecision, error) {
return &rpc.PermissionDecisionApproveOnce{}, nil
},
})
base64ImageData := "..."
mimeType := "image/png"
displayName := "screenshot.png"
session.Send(ctx, copilot.MessageOptions{
Prompt: "Describe what you see in this image",
Attachments: []copilot.Attachment{
&copilot.UserMessageAttachmentBlob{
Data: base64ImageData,
MIMEType: mimeType,
DisplayName: &displayName,
},
},
})
}
mimeType := "image/png"
displayName := "screenshot.png"
session.Send(ctx, copilot.MessageOptions{
Prompt: "Describe what you see in this image",
Attachments: []copilot.Attachment{
&copilot.UserMessageAttachmentBlob{
Data: base64ImageData, // base64-encoded string
MIMEType: mimeType,
DisplayName: &displayName,
},
},
})
using GitHub.Copilot;
using GitHub.Copilot.Rpc;
public static class BlobAttachmentExample
{
public static async Task Main()
{
await using var client = new CopilotClient();
await using var session = await client.CreateSessionAsync(new SessionConfig
{
Model = "gpt-4.1",
OnPermissionRequest = (req, inv) =>
Task.FromResult(PermissionDecision.ApproveOnce()),
});
var base64ImageData = "...";
await session.SendAsync(new MessageOptions
{
Prompt = "Describe what you see in this image",
Attachments = new List<UserMessageAttachment>
{
new UserMessageAttachmentBlob
{
Data = base64ImageData,
MimeType = "image/png",
DisplayName = "screenshot.png",
},
},
});
}
}
await session.SendAsync(new MessageOptions
{
Prompt = "Describe what you see in this image",
Attachments = new List<UserMessageAttachment>
{
new UserMessageAttachmentBlob
{
Data = base64ImageData,
MimeType = "image/png",
DisplayName = "screenshot.png",
},
},
});
import com.github.copilot.sdk.CopilotClient;
import com.github.copilot.sdk.events.*;
import com.github.copilot.sdk.json.*;
import java.util.List;
try (var client = new CopilotClient()) {
client.start().get();
var session = client.createSession(
new SessionConfig()
.setModel("gpt-4.1")
.setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
).get();
var base64ImageData = "..."; // your base64-encoded image
session.send(new MessageOptions()
.setPrompt("Describe what you see in this image")
.setAttachments(List.of(
new BlobAttachment()
.setData(base64ImageData)
.setMimeType("image/png")
.setDisplayName("screenshot.png")
))
).get();
}
지원되는 형식
지원되는 이미지 형식에는 JPG, PNG, GIF 및 기타 일반적인 이미지 형식이 포함됩니다. 파일 첨부 파일의 경우 런타임은 디스크에서 이미지를 읽고 필요에 따라 변환합니다. Blob 첨부 파일의 경우 base64 데이터 및 MIME 형식을 직접 제공합니다. 가장 널리 지원되는 형식이므로 최상의 결과를 위해 PNG 또는 JPEG를 사용합니다.
모델의 capabilities.limits.vision.supported_media_types 필드에는 모델에서 허용하는 정확한 MIME 형식이 나열됩니다.
자동 처리
런타임은 모델의 제약 조건에 맞게 이미지를 자동으로 처리합니다. 수동 크기 조정은 필요하지 않습니다.
- 모델의 차원 또는 크기 제한을 초과하는 이미지는 자동으로 크기 조정(가로 세로 비율 유지) 또는 품질 저하됩니다.
- 이미지를 처리한 후 제한 내에서 가져올 수 없는 경우 건너뛰고 LLM으로 전송되지 않습니다.
- 모델의
capabilities.limits.vision.max_prompt_image_size필드는 최대 이미지 크기(바이트)를 나타냅니다.
모델 기능 개체를 통해 런타임에 이러한 제한을 확인할 수 있습니다. 최상의 환경을 위해 합리적인 크기의 PNG 또는 JPEG 이미지를 사용합니다.
비전 모델 기능
모든 모델이 비전을 지원하는 것은 아닙니다. 이미지를 보내기 전에 모델의 기능을 확인합니다.
기능 필드
| Field | Type | Description |
|---|---|---|
capabilities.supports.vision | boolean | 모델이 이미지 입력을 처리할 수 있는지 여부 |
capabilities.limits.vision.supported_media_types | string[] | 모델이 허용하는 MIME 형식(예: ["image/png", "image/jpeg"] |
capabilities.limits.vision.max_prompt_images | number | 프롬프트당 최대 이미지 수 |
capabilities.limits.vision.max_prompt_image_size | number | 최대 이미지 크기(바이트) |
비전 제한 유형
interface VisionCapabilities {
vision?: {
supported_media_types: string[];
max_prompt_images: number;
max_prompt_image_size: number; // bytes
};
}
vision?: {
supported_media_types: string[];
max_prompt_images: number;
max_prompt_image_size: number; // bytes
};
이미지 결과 받기
도구가 이미지를 반환하는 경우(예: 스크린샷 또는 생성된 차트) 결과에는 base64로 인코딩된 데이터가 포함된 콘텐츠 블록이 포함 "image" 됩니다.
| Field | Type | Description |
|---|---|---|
type | "image" | 콘텐츠 블록 형식 판별자 |
data | string | Base64로 인코딩된 이미지 데이터 |
mimeType | string | MIME 형식(예: "image/png") |
이러한 이미지 블록은 tool.execution_complete 이벤트 결과에 표시됩니다. 전체 이벤트 수명 주기는 스트리밍 세션 이벤트 가이드를 참조하세요.
팁 및 제한 사항
| Tip | Details |
|---|---|
| PNG 또는 JPEG 직접 사용 | 변환 오버헤드를 방지합니다. 이는 LLM as-is 전송됩니다. |
| 이미지 크기를 합리적으로 유지 | 큰 이미지는 품질이 저하되어 중요한 세부 정보를 잃을 수 있습니다. |
| 파일 첨부 파일에 절대 경로 사용 | 런타임은 디스크에서 파일을 읽습니다. 상대 경로가 올바르게 확인되지 않을 수 있습니다. |
| 메모리 내 데이터에 Blob 첨부 파일 사용 | base64 데이터(예: 스크린샷, API 응답)가 이미 있는 경우 Blob은 불필요한 디스크 I/O를 방지합니다. |
| 먼저 비전 지원 확인 | 비전이 아닌 모델로 이미지를 보내면 시각적 이해 없이 토큰이 낭비됩니다. |
| 여러 이미지가 지원됩니다. | 한 메시지에 여러 첨부 파일을 모델의 max_prompt_images 제한까지 첨부합니다. |
| SVG는 지원되지 않습니다. | SVG 파일은 텍스트 기반이며 이미지 처리에서 제외됩니다. |
참고하십시오
- 스트리밍 세션 이벤트: 도구 결과 콘텐츠 블록을 포함한 이벤트 수명 주기
- 조향 및 대기열 관리: 첨부 파일이 포함된 후속 메시지 보내기