Capabilities

Capabilities (기능 선언)

AG-UI 프로토콜에서 에이전트의 동적 기능 탐지(Dynamic capability discovery)를 설명드릴게요.

출처: 문서

본문

AG-UI 프로토콜의 에이전트는 기능 탐지(capability discovery) 를 통해 런타임에 자신이 무엇을 지원하는지 선언할 수 있어요. 이 덕분에 클라이언트는 에이전트를 조회하고, 사용 가능한 기능에 따라 동작을 조정할 수 있습니다 — 추측하거나 가정을 하드코딩하지 않고요.

작동 방식 (How It Works)

AbstractAgent는 에이전트가 현재 지원하는 모든 것을 타입이 있는 스냅샷으로 반환하는 선택적 getCapabilities() 메서드를 선언해요. 이 메서드는 자신의 기능을 아는 에이전트 하위 클래스(LangGraph·ADK 통합 또는 직접 만든 것)가 구현하며, 전송 수단일 뿐이고 탐지 엔드포인트가 없는 순수 HttpAgent는 구현하지 않아요. 아래의 선택적 호출은 구현하지 않는 에이전트에 대해 undefined를 반환합니다:

// Any AbstractAgent subclass that implements getCapabilities(); a plain
// HttpAgent does not, and would yield undefined here.
const agent = new LangGraphAgent({ url: "https://my-agent.example.com/api" })

const capabilities = await agent.getCapabilities?.()

if (capabilities?.tools?.supported) {
  console.log(`Agent provides ${capabilities.tools.items?.length} tools`)
}

if (capabilities?.reasoning?.supported) {
  // Show reasoning UI toggle
}

핵심 원칙 (Key Principles)

  • 탐지만 (Discovery only) — 에이전트가 할 수 있는 것을 선언할 뿐, 협상(negotiation)은 없어요
  • 동적 (Dynamic) — 호출 시점의 현재 상태를 반환해요 (예: 도구가 추가되면 다음 호출이 반영)
  • 선택적 (Optional) — 구현하지 않는 에이전트는 undefined를 반환해요
  • 부재 = 알 수 없음 (Absent = unknown) — 지원하는 것만 선언하고, 생략된 필드는 해당 기능이 선언되지 않았다는 뜻이에요

AgentCapabilities 인터페이스 (The AgentCapabilities Interface)

기능은 타입이 있는 범주로 구성되며, 각 범주는 에이전트 기능의 서로 다른 측면을 나타냅니다:

interface AgentCapabilities {
  /** Agent identity and metadata. */
  identity?: IdentityCapabilities
  /** Supported transport mechanisms (SSE, WebSocket, binary, etc.). */
  transport?: TransportCapabilities
  /** Tools the agent provides and tool calling configuration. */
  tools?: ToolsCapabilities
  /** Output format support (structured output, MIME types). */
  output?: OutputCapabilities
  /** State and memory management (snapshots, deltas, persistence). */
  state?: StateCapabilities
  /** Multi-agent coordination (delegation, handoffs, sub-agents). */
  multiAgent?: MultiAgentCapabilities
  /** Reasoning and thinking support (chain-of-thought, encrypted thinking). */
  reasoning?: ReasoningCapabilities
  /** Multimodal input/output support organized by direction (input vs output). */
  multimodal?: MultimodalCapabilities
  /** Execution control and limits (code execution, timeouts, iteration caps). */
  execution?: ExecutionCapabilities
  /** Human-in-the-loop support (approvals, interventions, feedback). */
  humanInTheLoop?: HumanInTheLoopCapabilities
  /** Integration-specific capabilities not covered by the standard categories. */
  custom?: Record<string, unknown>
}

custom 필드는 표준 범주에 맞지 않는 통합별 기능을 위한 탈출구(escape hatch)예요.

기능 범주 (Capability Categories)

Identity (신원)

에이전트에 대한 기본 메타데이터예요. 탐지 UI, 에이전트 마켓플레이스, 디버깅에 유용합니다. 클라이언트가 에이전트 정보를 표시하길 원하거나, 여러 에이전트가 있고 사용자가 하나를 골라야 할 때 이들을 설정하세요.

interface IdentityCapabilities {
  /** Human-readable name shown in UIs and agent selectors. */
  name?: string
  /** The framework or platform powering this agent (e.g., "langgraph", "mastra", "crewai"). */
  type?: string
  /** What this agent does — helps users and routing logic decide when to use it. */
  description?: string
  /** Semantic version of the agent (e.g., "1.2.0"). Useful for compatibility checks. */
  version?: string
  /** Organization or team that maintains this agent. */
  provider?: string
  /** URL to the agent's documentation or homepage. */
  documentationUrl?: string
  /** Arbitrary key-value pairs for integration-specific identity info. */
  metadata?: Record<string, unknown>
}

Transport (전송)

에이전트가 지원하는 전송 메커니즘을 선언해요. 클라이언트는 이를 사용해 최상의 연결 전략을 고릅니다. 에이전트가 실제로 처리하는 전송에 대해서만 플래그를 true로 설정하세요 — 지원하지 않는 것은 생략하거나 false로 설정해요.

interface TransportCapabilities {
  /** Set `true` if the agent streams responses via SSE. Most agents enable this. */
  streaming?: boolean
  /** Set `true` if the agent accepts persistent WebSocket connections. */
  websocket?: boolean
  /** Set `true` if the agent supports the AG-UI binary protocol (protobuf over HTTP). */
  httpBinary?: boolean
  /** Set `true` if the agent can send async updates via webhooks after a run finishes. */
  pushNotifications?: boolean
  /** Set `true` if the agent supports resuming interrupted streams via sequence numbers. */
  resumable?: boolean
}

Tools (도구)

도구 호출 기능을 나타내요. 에이전트가 자체적으로 제공하는 도구(items에 나열)와 클라이언트가 RunAgentInput.tools로 런타임에 전달하는 도구를 구분합니다. 에이전트가 함수를 호출하거나, 웹을 검색하거나, 코드를 실행할 수 있을 때 활성화하세요.

interface ToolsCapabilities {
  /** Set `true` if the agent can make tool calls at all. Set `false` to explicitly
   *  signal tool calling is disabled even if items are present. */
  supported?: boolean
  /** The tools this agent provides on its own (full JSON Schema definitions).
   *  These are distinct from client-provided tools passed in `RunAgentInput.tools`. */
  items?: Tool[]
  /** Set `true` if the agent can invoke multiple tools concurrently within a single step. */
  parallelCalls?: boolean
  /** Set `true` if the agent accepts and uses tools provided by the client at runtime. */
  clientProvided?: boolean
}

Output (출력)

출력 형식 지원을 나타내요. 에이전트가 JSON 스키마에 맞는 응답을 반환할 수 있다면 structuredOutput를 활성화하세요 — 프로그래매틱 소비에 유용합니다.

interface OutputCapabilities {
  /** Set `true` if the agent can produce structured JSON output matching a provided schema. */
  structuredOutput?: boolean
  /** MIME types the agent can produce (e.g., `["text/plain", "application/json"]`).
   *  Omit if the agent only produces plain text. */
  supportedMimeTypes?: string[]
}

State (상태)

상태와 메모리 관리 기능을 나타내요. 에이전트가 공유 상태를 어떻게 다루는지, 대화 컨텍스트가 실행 간에 유지되는지를 클라이언트에 알려줍니다.

interface StateCapabilities {
  /** Set `true` if the agent emits `STATE_SNAPSHOT` events (full state replacement). */
  snapshots?: boolean
  /** Set `true` if the agent emits `STATE_DELTA` events (JSON Patch incremental updates). */
  deltas?: boolean
  /** Set `true` if the agent has long-term memory beyond the current thread
   *  (e.g., vector store, knowledge base, or cross-session recall). */
  memory?: boolean
  /** Set `true` if state is preserved across multiple runs within the same thread.
   *  When `false`, state resets on each run. */
  persistentState?: boolean
}

Multi-Agent (다중 에이전트)

다중 에이전트 조정 기능을 나타내요. 에이전트가 다른 에이전트에게 작업을 오케스트레이션하거나 핸드오프할 수 있을 때 활성화하세요.

interface MultiAgentCapabilities {
  /** Set `true` if the agent participates in any form of multi-agent coordination. */
  supported?: boolean
  /** Set `true` if the agent can delegate subtasks to other agents while retaining control. */
  delegation?: boolean
  /** Set `true` if the agent can transfer the conversation entirely to another agent. */
  handoffs?: boolean
  /** List of sub-agents this agent can invoke. Helps clients build agent selection UIs. */
  subagents?: Array<{ name: string; description?: string }>
}

Reasoning (추론)

추론/사고 기능을 나타내요. 에이전트가 내부 사고 과정(예: chain-of-thought, extended thinking)을 노출할 때 활성화하세요.

interface ReasoningCapabilities {
  /** Set `true` if the agent produces reasoning/thinking tokens visible to the client. */
  supported?: boolean
  /** Set `true` if reasoning tokens are streamed incrementally (vs. returned all at once). */
  streaming?: boolean
  /** Set `true` if reasoning content is encrypted (zero-data-retention mode).
   *  Clients should expect opaque `encryptedValue` fields instead of readable content. */
  encrypted?: boolean
}

Multimodal (멀티모달)

멀티모달 입력·출력 지원을 input과 output 하위 객체로 구성해, 클라이언트가 에이전트가 받아들이는 것과 생성하는 것을 독립적으로 조회할 수 있게 해요. 클라이언트는 이를 사용해 파일 업로드 버튼, 오디오 녹음기, 이미지 선택기 등을 표시/숨깁니다.

interface MultimodalInputCapabilities {
  /** Set `true` if the agent can process image inputs (e.g., screenshots, photos). */
  image?: boolean
  /** Set `true` if the agent can process audio inputs (speech, recordings). */
  audio?: boolean
  /** Set `true` if the agent can process video inputs. */
  video?: boolean
  /** Set `true` if the agent can process PDF documents. */
  pdf?: boolean
  /** Set `true` if the agent can process arbitrary file uploads. */
  file?: boolean
}

interface MultimodalOutputCapabilities {
  /** Set `true` if the agent can generate images as part of its response. */
  image?: boolean
  /** Set `true` if the agent can produce audio output (text-to-speech, audio files). */
  audio?: boolean
}

interface MultimodalCapabilities {
  /** Modalities the agent can accept as input (images, audio, video, PDFs, files). */
  input?: MultimodalInputCapabilities
  /** Modalities the agent can produce as output (images, audio). */
  output?: MultimodalOutputCapabilities
}

Execution (실행)

실행 제어와 한계를 나타내요. 클라이언트가 에이전트 실행이 얼마나 오래 걸리거나 몇 단계를 거칠지 기대치를 세울 수 있도록 선언하세요.

interface ExecutionCapabilities {
  /** Set `true` if the agent can execute code (e.g., Python, JavaScript) during a run. */
  codeExecution?: boolean
  /** Set `true` if code execution happens in a sandboxed/isolated environment.
   *  Only meaningful when `codeExecution` is `true`. */
  sandboxed?: boolean
  /** Maximum number of tool-call/reasoning iterations the agent will perform per run.
   *  Helps clients display progress or set timeout expectations. */
  maxIterations?: number
  /** Maximum wall-clock time (in milliseconds) the agent will run before timing out. */
  maxExecutionTime?: number
}

Human-in-the-Loop (인간-개입)

인간 개입 상호작용 지원을 나타내요. 에이전트가 계속 진행하기 전에 인간의 입력·승인·피드백을 요청하도록 실행을 일시중지할 수 있을 때 활성화하세요.

interface HumanInTheLoopCapabilities {
  /** Set `true` if the agent supports any form of human-in-the-loop interaction. */
  supported?: boolean
  /** Set `true` if the agent can pause and request explicit approval before
   *  performing sensitive actions (e.g., sending emails, deleting data). */
  approvals?: boolean
  /** Set `true` if the agent allows humans to intervene and modify its plan mid-execution. */
  interventions?: boolean
  /** Set `true` if the agent can incorporate user feedback (thumbs up/down, corrections)
   *  to improve its behavior within the current session. */
  feedback?: boolean
  /** Set `true` if the agent participates in the AG-UI interrupt protocol (emits
   *  `RunFinished` with `outcome: { type: "interrupt", interrupts: [...] }`,
   *  accepts `RunAgentInput.resume`). */
  interrupts?: boolean
  /** Set `true` if tool-call interrupts accept `editedArgs` in the resume payload.
   *  Only meaningful when `interrupts` is `true`. */
  approveWithEdits?: boolean
}

프로토콜 전체 스펙은 Interrupts 문서를 참고하세요.

getCapabilities() 구현하기 (Implementing getCapabilities())

커스텀 에이전트 (Custom Agents)

에이전트 하위 클래스에서 getCapabilities()를 구현하고, 실제로 지원하는 기능만 반환하세요:

import { AbstractAgent, AgentCapabilities } from "@ag-ui/client"

class MyAgent extends AbstractAgent {
  async getCapabilities(): Promise<AgentCapabilities> {
    return {
      identity: {
        name: "my-agent",
        description: "A custom agent with tool support",
        version: "1.0.0",
      },
      transport: {
        streaming: true,
      },
      tools: {
        supported: true,
        items: this.getRegisteredTools(),
        clientProvided: true,
      },
      state: {
        snapshots: true,
        deltas: true,
      },
    }
  }

  // ... run() implementation
}

동적 기능 (Dynamic Capabilities)

getCapabilities()는 살아있는 스냅샷을 반환하므로 에이전트의 현재 상태를 그대로 반영해요:

const agent = new MyAgent(config)

let caps = await agent.getCapabilities()
console.log(caps.tools?.items?.length) // 5

// Register more tools at runtime
agent.registerTool(newTool)

caps = await agent.getCapabilities()
console.log(caps.tools?.items?.length) // 6

클라이언트 사용 패턴 (Client Usage Patterns)

적응형 UI (Adaptive UI)

에이전트가 지원하는 것에 따라 UI 컴포넌트를 렌더링하세요:

const capabilities = await agent.getCapabilities?.()

// Only show reasoning panel if supported
if (capabilities?.reasoning?.supported) {
  showReasoningPanel()
}

// Only show sub-agent selector if available
if (capabilities?.multiAgent?.subagents?.length) {
  showSubAgentSelector(capabilities.multiAgent.subagents)
}

// Only show approval UI if HITL is supported
if (capabilities?.humanInTheLoop?.approvals) {
  enableApprovalWorkflow()
}

기능 게이팅 (Feature Gating)

런타임에 실패하는 대신 에이전트가 지원하지 않는 기능을 비활성화하세요:

const capabilities = await agent.getCapabilities?.()

// Gate on an explicit declaration: an omitted field means undeclared, not unsupported.
const canUseStructuredOutput = capabilities?.output?.structuredOutput === true
const canStream = capabilities?.transport?.streaming === true

커스텀 기능 (Custom Capabilities)

custom 필드를 통해 통합별 기능에 접근하세요:

const capabilities = await agent.getCapabilities?.()

const rateLimit = capabilities?.custom?.rateLimit as
  | { maxRequestsPerMinute: number }
  | undefined

if (rateLimit) {
  configureThrottling(rateLimit.maxRequestsPerMinute)
}

더 알아보기 (Learn more)