- **Capabilities(μλ μ μΈ)**λ AG-UI νλ‘ν μ½μμ μμ΄μ νΈκ° λ°νμμ μμ μ΄ μ§μνλ κΈ°λ₯μ ν΄λΌμ΄μΈνΈμ λ ΈμΆνλ λ°κ²¬(discovery) λ©μ»€λμ¦
- AbstractAgentμ
getCapabilities()κ° λ°ννλ νμ νλ λ₯λ ₯ μ€λ μ· - νμ(negotiation)μ΄ μλ λ¨λ°©ν₯ μ μΈ λ°©μμ μΈν°νμ΄μ€
- λͺ μλμ§ μμ νλλ βλ―Έμ μΈ(unknown)βμΌλ‘ ν΄μλλ λΆλΆ μ μΈ κ°λ₯ν μ΅μ λ ꡬ쑰
- λꡬ λ±λ‘Β·ν΄μ μ²λΌ μνκ° λ³νλ©΄ λ€μ νΈμΆμ μ¦μ λ°μλλ λΌμ΄λΈ μ€λ μ·
ν΄λΉ κ°λ μ΄ νμν μ΄μ
- ν΄λΌμ΄μΈνΈκ° μμ΄μ νΈ κΈ°λ₯μ μΆμΈ‘νκ±°λ νλμ½λ©νμ§ μκ³ λ UI/νλ‘μ°λ₯Ό μ μμ μΌλ‘ ꡬμ±ν μ μμ΄μΌ ν¨
- λꡬ·μΆλ‘ Β·λ©ν°λͺ¨λ¬Β·HITL λ± μ΄μ§μ μΈ κΈ°λ₯κ΅°μ λ¨μΌ νμ€ μ€ν€λ§λ‘ λ ΈμΆν ν΅μΌλ μ°½κ΅¬κ° νμ
- λ°νμμ λκ΅¬κ° μΆκ°/μ κ±°λκ±°λ λͺ¨λκ° λ°λ λ λμ μΌλ‘ λ°μλ μ μμ΄μΌ ν¨
- μμ΄μ νΈ λ§μΌνλ μ΄μ€Β·λΌμ°ν λ‘μ§μμ μμ΄μ νΈ λΉκ΅Β·μ νμ κ°κ΄μ κ·Όκ±°κ° νμ
AS-IS
sequenceDiagram autonumber participant Client participant Agent Client->>Client: "μ΄ μμ΄μ νΈκ° tools μ§μνλ?" μΆμΈ‘ Client->>Agent: run() with tool calls Agent-->>Client: λ°νμ μ€λ₯ λλ 무μλ¨ Note over Client: νλμ½λ©λ κ°μ μ μμ‘΄<br/>μ€ν¨ νμμΌ λ―Έμ§μ λ°κ²¬
TO-BE
sequenceDiagram autonumber participant Client participant Agent Client->>Agent: getCapabilities() Agent-->>Client: AgentCapabilities snapshot Client->>Client: tools.supported, reasoning.supported λ± κ²μ¬ Client->>Client: μ§μ κΈ°λ₯λ§ UIμ λ ΈμΆ (Adaptive UI) Client->>Agent: run() β κ²μ¦λ κΈ°λ₯λ§ μ¬μ© Agent-->>Client: μ μ μλ΅
ν΅μ¬ μμΉ 4κ°μ§
μμΉ 1. Discovery only β λ°κ²¬μ΄μ§ νμμ΄ μλλ€
μμ΄μ νΈκ° μμ μ΄ ν μ μλ κ²μ μ μΈν λΏμ΄κ³ , ν΄λΌμ΄μΈνΈκ° λ₯λ ₯μ μμ²Β·κ΅μνμ§ μλλ€. λ¨λ°©ν₯μ΄λ€.
μμΉ 2. Dynamic β νΈμΆ μμ μ λΌμ΄λΈ μν
getCapabilities()λ μΊμλ μ μ λ©νλ°μ΄ν°κ° μλλΌ νΈμΆ μμ μ νμ¬ μνλ€. λꡬλ₯Ό λ±λ‘νλ©΄ λ€μ νΈμΆμ tools.itemsμ κ³§λ°λ‘ λ°μλλ€.
let caps = await agent.getCapabilities()
console.log(caps.tools?.items?.length) // 5
agent.registerTool(newTool)
caps = await agent.getCapabilities()
console.log(caps.tools?.items?.length) // 6μμΉ 3. Optional β ꡬν μμ²΄κ° μ΅μ
ꡬννμ§ μμ μμ΄μ νΈλ undefinedλ₯Ό λ°ννλ€. λ°λΌμ ν΄λΌμ΄μΈνΈλ νμ await agent.getCapabilities?.() ννμ μ΅μ
λ 체μ΄λμΌλ‘ νΈμΆν΄μΌ νλ€.
μμΉ 4. Absent = unknown β λΆμ¬λ λ―Έμ§μμ΄ μλλΌ λ―Έμ μΈ
tools νλλ₯Ό μλ΅ν κ²μ΄ βλꡬ λ―Έμ§μβμ λ»νμ§λ μλλ€. μ μΈνμ§ μμμμ μλ―Έν λΏμ΄λ€. λͺ
μμ μΌλ‘ μ°¨λ¨νλ €λ©΄ supported: falseλ₯Ό μ¨μΌ νλ€.
AgentCapabilities μΈν°νμ΄μ€ β 11κ° μΉ΄ν κ³ λ¦¬
| μΉ΄ν κ³ λ¦¬ | μν | λν νλ |
|---|---|---|
identity | μμ΄μ νΈ λ©νλ°μ΄ν° | name, type, version, provider, documentationUrl |
transport | μ μ‘ λ°©μ (AG-UI Serialization) | streaming(SSE), websocket, httpBinary(protobuf), pushNotifications, resumable |
tools | λꡬ νΈμΆ | supported, items[], parallelCalls, clientProvided |
output | μΆλ ₯ ν¬λ§· | structuredOutput, supportedMimeTypes |
state | μν/λ©λͺ¨λ¦¬ | snapshots, deltas, memory, persistentState |
multiAgent | λ€μ€ μμ΄μ νΈ νλ ₯ | supported, delegation, handoffs, subAgents |
reasoning | μΆλ‘ /μ¬κ³ λ ΈμΆ | supported, streaming, encrypted |
multimodal | μ μΆλ ₯ λͺ¨λ¬λ¦¬ν° | input.{image,audio,video,pdf,file}, output.{image,audio} |
execution | μ€ν μ μ΄ | codeExecution, sandboxed, maxIterations, maxExecutionTime |
humanInTheLoop | μΈκ° κ°μ | supported, approvals, interventions, feedback |
custom | νμ€ μΈ νμ₯ | Record<string, unknown> (escape hatch) |
interface AgentCapabilities {
identity?: IdentityCapabilities
transport?: TransportCapabilities
tools?: ToolsCapabilities
output?: OutputCapabilities
state?: StateCapabilities
multiAgent?: MultiAgentCapabilities
reasoning?: ReasoningCapabilities
multimodal?: MultimodalCapabilities
execution?: ExecutionCapabilities
humanInTheLoop?: HumanInTheLoopCapabilities
custom?: Record<string, unknown>
}tools.items vs RunAgentInput.tools
tools.itemsλ μμ΄μ νΈκ° λ΄μ₯ν λꡬ, RunAgentInput.toolsλ ν΄λΌμ΄μΈνΈκ° λ°νμμ μ£Όμ
νλ λꡬλ€. λμ μλ‘ λ€λ₯Έ μΆμ²μ λꡬ λͺ©λ‘μ΄λ©°, tools.clientProvided: trueλ νμλ₯Ό λ°μλ€μΌ μ μλ€λ μ νΈλ€.
state β μ€λ μ·κ³Ό λΈνμ ꡬλΆ
AG-UI State Managementμμ λ€λ£¨λ STATE_SNAPSHOT(μ 체 κ΅μ²΄)κ³Ό STATE_DELTA(JSON Patch κΈ°λ° λΆλΆ κ°±μ , delta) μ€ μ΄λ€ κ²μ μ΄λ²€νΈλ‘ λ°ννλμ§λ₯Ό κ°κ° snapshots/deltas νλκ·Έλ‘ μ μΈνλ€. persistentStateλ κ°μ thread λ΄μμ run κ° μνκ° μ μ§λλμ§ μ¬λΆλ€.
reasoning.encrypted β 무μμ μλ―Ένλ
encrypted: trueλ zero-data-retention λͺ¨λλ‘, ν΄λΌμ΄μΈνΈλ μ½μ μ μλ μΆλ‘ ν
μ€νΈ λμ λΆν¬λͺ
ν encryptedValue νλλ₯Ό λ°λλ€. UIμ μΆλ‘ ν¨λμ κ·Έλλ‘ λ
ΈμΆνλ©΄ μ λλ€λ μ νΈλ€.
ꡬν μμ
컀μ€ν μμ΄μ νΈμμ μ μΈ
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,
},
}
}
}μ μΈνμ§ μμ μΉ΄ν κ³ λ¦¬(reasoning, multimodal, execution λ±)λ μλμΌλ‘ βλ―Έμ μΈβ μνκ° λλ€.
ν΄λΌμ΄μΈνΈ νμ© ν¨ν΄ 3κ°μ§
ν¨ν΄ 1. Adaptive UI β UI μ»΄ν¬λνΈ κ°μμ± μ μ΄
const caps = await agent.getCapabilities?.()
if (caps?.reasoning?.supported) showReasoningPanel()
if (caps?.multiAgent?.subAgents?.length) showSubAgentSelector(caps.multiAgent.subAgents)
if (caps?.humanInTheLoop?.approvals) enableApprovalWorkflow()ν¨ν΄ 2. Feature Gating β λ―Έμ§μ κΈ°λ₯ μ¬μ μ°¨λ¨
const canUseStructuredOutput = caps?.output?.structuredOutput ?? false
const canStream = caps?.transport?.streaming ?? falseλ°νμ μ€ν¨ λμ μ¬μ μ λΉνμ±ννμ¬ μ¬μ©μ κ²½νμ μΌκ΄λκ² μ μ§νλ€. ?? falseλ‘ λ―Έμ μΈ μΌμ΄μ€λ₯Ό μμ ν μͺ½(λ―Έμ§μ)μΌλ‘ μ’νλ κ²μ΄ κ΄μ© ν¨ν΄μ΄λ€.
ν¨ν΄ 3. Custom Capabilities β ν΅ν©λ³ νμ₯
const rateLimit = caps?.custom?.rateLimit as
| { maxRequestsPerMinute: number }
| undefined
if (rateLimit) configureThrottling(rateLimit.maxRequestsPerMinute)νμ€ μΉ΄ν
κ³ λ¦¬μ μλ μ 보(λ μ΄νΈ 리λ°, λΉμ© λ¨κ°, λ²€λ μλ³μ λ±)λ customμΌλ‘ λ
ΈμΆνλ€. νμ
μ ν΅ν©λ³ ν©μμ μμ‘΄νλ―λ‘ ν΄λΌμ΄μΈνΈ μΈ‘μμ λ¨μΈ(assert)μ΄ νμνλ€.