1.0으로 마이그레이션하기
1.0으로 마이그레이션하기
AG-UI 1.0으로 옮기는 애플리케이션·통합에 SDK별로 무엇이 바뀌고, 무엇이 바뀌지 않는지 설명해 드릴게요. 프로토콜 수준의 변경은 스펙의 Key Changes에 나열되어 있으니, 이 페이지는 그중 각각이 이미 있는 코드에 무슨 의미인지에 집중할게요.
출처: 문서
본문
AG-UI 1.0은 스펙이 뒤에 붙은 첫 릴리스예요: schema가 단일 진실 원천이고, 모든 SDK의 프로토콜 타입이 그것에서 생성되며, 예전에는 TypeScript 클라이언트에만 있던 동작 규칙이 문서화됐습니다. 바뀐 것 대부분은 덧붙여지는(additive) 성격이에요. 이 페이지는 그렇지 않은 부분 — SDK별로 손봐야 할 것과 저절로 계속 동작하는 것 — 을 다룹니다.
계속 동작하는 것
0.x 에이전트는 1.0 클라이언트와 계속 동작해요. TypeScript 클라이언트는 항상 켜져 있는 호환성 경계를 담아, 들어오는 스트림에서 만나는 은퇴된 형태를 번역합니다 — 다섯 개의 THINKING_* 이벤트는 REASONING_* 동등 이벤트가 되고, 레거시 binary 콘텐츠 파트는 그것의 미디어 타입이 지칭하는 미디어 파트가 되며, 역사적으로 받아들여졌던 전체 선택적 null 필드는 검증 전에 없어집니다. 모든 인바운드 번역은 경고를 냅니다. 이 shim들은 그것의 대체물과 만료일과 함께 DEPRECATIONS.md에 기록돼 있어요. 만료일은 잠정적입니다 — 각 shim이 작성된 시점에서 12개월, 1.0 릴리스가 늦어지면 재일정되죠 — 그 후로 은퇴된 형태는 전혀 동작하지 않게 됩니다.
1.0 에이전트는 0.x 클라이언트와 계속 동작해요. 1.0이 추가하는 모든 것 — RUN_FINISHED.outcome, 서브에이전트 이벤트, protocolVersion, 액티비티 이벤트 — 은 선택적이거나 새 이벤트 타입이고, 버전 필드 이전의 클라이언트는 모르는 것을 무시합니다.
와이어는 같아요. SSE 위 JSON과 protobuf 바인딩은 프레이밍이 변하지 않았습니다. 오늘 보내는 필드 이름이 1.0이 읽는 필드 이름이고, 예외는 이 페이지에 있는 것들뿐이에요.
TypeScript
TypeScript SDK는 셋 중 가장 많이 바뀌어요. 프로토콜의 동작이 예전에 그곳에 정의됐기 때문이에요.
전체 선택적 null 필드 생략하기
선택적 프로토콜 필드는 null 대신 없어져야 해요. rawEvent, RUN_FINISHED.result, forwardedProps가 포함됩니다. EventEncoder와 나가는 HTTP 입력은 전송 전에 이 필드들을 생략해요. 인메모리 에이전트에서도 정규 형태를 내보내세요.
이전 SDK가 전체 선택적 null을 받아들였던 곳에서는 이전 프로듀서들이 호환됩니다. 검증 전에 클라이언트는 그것을 없는 필드로 번역하고, rawEvent, RUN_FINISHED.result, SUBAGENT_FINISHED.result, resume-entry payload, 미디어 파트 metadata(image, audio, video, document), 도구 parameters, RunAgentInput.forwardedProps에 대해 경고합니다. 이것은 인메모리 실행, 재연결, SSE, protobuf에 적용되며, 이벤트에 포함된 메시지와 입력 에코도 포함해요. 구독자는 정규화된 이벤트를 받습니다: 예를 들어 옛 RUN_FINISHED.result: null은 없는 result가 됩니다.
직접 스키마 검증은 여전히 엄격하며 클라이언트의 이벤트 호환성 경계를 호출하지 않아요. 오래된 RunAgentInput 값을 받아들이는 요청 핸들러는 RunAgentInputSchema.parse를 호출하기 전에 역사적으로 받아들였던 선택적 null을 로컬에서 생략해야 해요: forwardedProps, tools[].parameters, resume[].payload, 그리고 messages[].content[]에 있는 image/audio/video/document 파트의 metadata. 애플리케이션 데이터에서 null을 재귀적으로 제거하거나 이미 null을 거부했던 필드에서 null을 제거하지 마세요. CopilotKit의 공유 run/connect 요청 파서는 이것을 로컬 호환성 예외로 처리합니다; AG-UI는 공개 요청 정규화 헬퍼를 노출하지 않아요. 기존 RunAgentInput.state: null 파서 허용은 여전히 undefined를 산출해요.
이 호환성은 역사적으로 받아들였던 필드에 한정됩니다. 이벤트나 메시지 metadata: null과 parentRunId: null은 여전히 유효하지 않아요. CUSTOM.value 같은 필수 JSON 페이로드, 그리고 상태·메타데이터·기타 애플리케이션 데이터 안의 null 값은 유효하게 유지되며 보존됩니다.
zod는 @ag-ui/core의 선택적 peer dependency예요
@ag-ui/core의 메인 엔트리는 타입과 상수만 있고 절대 zod를 로드하지 않아요. 검증자는 서브패스(subpath)에 있으며, 그것을 import하려면 zod(3.25.18 이상, 또는 어떤 4.x)가 필요해요.
// before
import { EventSchemas, UserMessageSchema, EventType } from "@ag-ui/core";
// after
import { EventType } from "@ag-ui/core";
import { EventSchemas, UserMessageSchema } from "@ag-ui/core/schemas";
npm install @ag-ui/core # types only — nothing else to install
npm install @ag-ui/core zod # if you use the validators
모든 검증자가 이동해요. 역사적 별칭(EventSchemas, *InputPartSchema 이름들, OptionalMetadataSchema)과 capability 스키마를 포함해서요. @ag-ui/client는 그것들을 더 이상 재수출하지 않아요 — core의 메인 엔트리를 재수출하고, 그것들은 거기에 없거든요. @ag-ui/client 자체는 여전히 zod에 의존합니다. 그 강제(enforcement) 단계가 zod로 검증하기 때문이에요; 클라이언트 설치 방식은 아무것도 바뀌지 않아요.
알 수 없는 자료가 더 이상 당신 코드에 닿지 않아요
클라이언트는 모든 경로에서 미들웨어 뒤에 강제 단계 하나를 가져요. 타입을 아무도 인식하지 못하는 이벤트는 경고와 함께 버려집니다. 알려진 이벤트의 알 수 없는 속성은 그것의 경로를 지칭하는 경고와 함께 제거됩니다. 프로토콜이 정의한 필드에 형식이 잘못된 값 — 문자열이 와야 하는데 숫자가 온 것 — 은 항상 그랬듯 실행을 실패시킵니다.
구독자에서 이벤트의 비표준 속성을 읽고 있었다면, 그 속성은 구독자가 보기 전에 사라져요. 추가 데이터를 위한 공인 채널은 metadata인데, 그것은 모든 이벤트와 메시지에서 키로 열려 있고 절대 제거되지 않아요.
같은 것이 보내는 쪽에도 적용됩니다: RunAgentInput의 알 수 없는 키는 전송 전에 제거됩니다. 정확히 그 목적을 위해 존재하는 필드는 forwardedProps로, 어떤 JSON이든 에이전트에 그대로 전달합니다.
1.0에서 더 엄격해진 동작
클라이언트가 예전에 느슨하게, 또는 한 경로에서만 적용하던 두 규칙이 이제 어디서나 적용돼요. 각각 조용히 성공하던 것을 실행 실패로 바꿉니다.
추론 열기/닫기 규율이 검증돼요. 아무것도 열지 않은 메시지를 지칭하는 REASONING_MESSAGE_CONTENT나 REASONING_MESSAGE_END, 열지 않고 닫힌 추론 스팬(span), 실행이 끝날 때 아직 열려 있는 스팬이나 메시지 — 모두 실행을 실패시킵니다. 고아 조각과 재열기는 1.0 전에 이미 THINKING_*에 대해 거부됐어요; RUN_FINISHED에서 열린 채 남은 스팬이나 메시지로 실행을 실패시키는 것은 새로우며, 텍스트 메시지와 도구 호출이 이미 하던 것과 일치합니다. 스팬과 추론 메시지는 별도의 네임스페이스예요 — THINKING_*과 달리 추론 메시지가 스팬 안에 있어야 할 필요는 없고, REASONING_START id가 추론 메시지를 열지 않아요.
강제 보장이 모든 경로에서 성립해요. 알 수 없는 자료는 경고와 함께 제거되고 형식이 잘못된 알려진 값은 치명적이에요 — 이제 그것이 미들웨어가 설치된 상태와 protobuf 바인딩 위에서도, 평범한 SSE 경로에서만이 아니라 참이에요. 그 경로들에서 조용히 사라지던 자료 — 미들웨어 체인 안에서 확장된 청크의 인식되지 않은 속성, protobuf 디코더를 건너는 알 수 없는 메시지 역할이나 패치 연산 — 이제 강제까지 타고 가서 버려지는 곳에서 보고됩니다.
RUN_ERROR는 변하지 않아요, 그리고 그것은 의도적이에요. 프로듀서가 보낸 RUN_ERROR는 잘 형성된 스트림이에요 — 에이전트가 자기 실행이 실패했음을 정직하게 보고하는 것은 프로토콜 위반이 아니죠 — 그래서 클라이언트는 그것을 받아들여요: 이벤트는 onRunErrorEvent로 전달되고, 스트림은 계속되며, runAgent()는 0.x에서처럼 정확히 해소됩니다. RUN_ERROR 이후의 RUN_STARTED는 같은 스트림에서 새 실행을 시작하고, 그 실행이 만드는 모든 것이 적용됩니다. 실행이 자기 실패를 보고할 때 거부된 프로미스가 필요하다면, 자신의 onRunErrorEvent 구독자에서 그것을 던지세요; 클라이언트는 당신을 위해 하지 않아요.
공개 API에서 은퇴한 것
- 다섯 개의
THINKING_*이벤트 — enum 멤버, 타입, 스키마, 팩토리.REASONING_*를 내보내세요; 들어오는THINKING_*스트림은 위의 경계에서 여전히 번역됩니다. BinaryInputContent({ type: "binary" }).source를 가진 미디어 파트 —image,audio,video,document— 를 사용하세요. 들어오는 레거시 파트는 여전히 번역됩니다.@ag-ui/client의stripUnknown과StripResult. 그것들은 강제 단계의 내부였어요.
이름 변경과 타입 변경
SubAgentInfo→SubagentInfo,AgentCapabilities의multiAgent.subAgents→subagents. 와이어 키도 함께 바뀌고 별칭이 없어요: 여전히subAgents를 담은 선언은 그 키가 알 수 없는 것으로 취급됩니다. 프로토콜은 그 단어를 어디서든 하나로 철자해요(subagentRunId).RunAgentInput.tools와.context는 TypeScript 타입에서 비선택적(non-optional)이에요. 와이어에서 없으면 여전히 빈 것을 뜻하고, SDK는 그것을[]로 제시하므로 하류에서 좁힐 필요가 없어요.AbstractAgent.maxVersion은maxProtocolVersion으로 deprecated예요. 옛 이름의 오버라이드는 여전히 동작하고 프로세스당 한 번 경고합니다.- 콘텐츠 파트는 방향이 아니라 그것이 무엇인지로 이름 붙여졌어요:
InputContent→ContentPart,TextInputContent→TextPart,ImageInputContent→ImagePart(audio, video, document 동일),InputContentSource→PartSource,InputContentDataSource→DataSource,InputContentUrlSource→UrlSource, 그리고 대응하는...Schema검증자들. 옛 이름은 같은 타입·검증자의 deprecated 별칭으로 내보내지므로 아무것도 깨지지 않아요; 와이어type값은 변하지 않습니다. PartSource에 세 번째 가지인FileSource(type: "file")가 있어요: 모델 프로바이더가 이미 업로드된 바이트에 대해 발급한 핸들이에요.source.type에서 완전히(exhaustively) 분기하는 코드는 그것을 위한 case가 필요해요. 그것의value를 URL로 취급하지 마세요; 에이전트가 핸들을 프로바이더에 넘길 수 없으면, 모델이 받을 수 없는 어떤 파트든 그렇듯 경고와 함께 파트를 건너뛰세요.ToolMessage.content와ToolCallResultEvent.content는UserMessage.content가 이미 그랬듯string | ContentPart[]예요. 도구 결과를 문자열 슬롯에 그대로 넘기던 코드는 먼저 좁혀요;@ag-ui/core의contentToText()가 텍스트 파트를 연결해서 주고,contentHasMedia()가 그 평탄화가 무엇을 잃을지 말해 줘요. 레거시ActionExecutionResult브리지는 이렇게 평탄화하고 경고합니다.- 모든 콘텐츠 파트는 선택적
id를,TextPart는 미디어 파트가 이미 가졌던 선택적metadata를 가져요. - capability의
execution.maxIterations와maxExecutionTime은 JavaScript 안전 범위 안의 음이 아닌 정수로 검증돼요.
새롭고, 알아 둘 가치가 있는 것
클라이언트는 모든 RunAgentInput에서 protocolVersion: "1.0"을 선언하고 RUN_STARTED에서 프로듀서의 답을 읽으며, 프로듀서가 더 새롭거나 해석 불가능한 버전을 말하면 경고합니다. maxProtocolVersion을 이 클라이언트 패키지 자신의 버전보다 아래로 고정하면, 알 수 없는 멤버를 거부할 피어를 위해 그 필드를 생략합니다.
Protobuf 디코딩은 단수 메시지 필드의 반복 발생을 병합합니다. 중첩 메시지, 메타데이터, 실행 입력을 포함해서요. 이후 스칼라 값이 이기고, 반복 목록 항목은 순서대로 추가되며, 생략된 필드는 이전 값을 보존합니다. TypeScript와 .NET은 같은 protobuf 병합 규칙을 따라요.
Python
Python SDK는 프로듀서 측이에요: 에이전트가 내보내는 형태를 정의합니다. 변경은 더 좁고, 그중 하나는 그 출력을 파싱하는 사람이라면 누구에게나 영향을 미쳐요.
없는 필드는 생략되고, 절대 null이 아니에요
값이 없는 필드는 null로 쓰는 대신 JSON에서 빠집니다. 이것은 1.0보다 앞서, ag-ui-protocol 0.1.20에서 출시됐으므로, 그 이전 버전에서 온 경우에만 마이그레이션 단계예요 — 하지만 에이전트 출력을 파싱하는 어떤 것에 가장 영향을 줄 가능성이 높은 변경이에요. if payload["parentMessageId"] is None이나 그 동등한 것을 하는 리더는 "parentMessageId" not in payload가 필요해요. 값인 null — 메타데이터 키 아래, 상태 스냅샷 안, null의 JSON Patch add — 은 정확히 보존됩니다; 전체 없어진 필드를 대신하는 null만 사라져요.
손으로 쓴 모델을 생성 모델이 대체해요
ag_ui.core는 아래에서 은퇴·이름변경된 것을 제외하고 내보내던 모든 이름을 유지하며, 이제 생성된 소스에서 재수출되고, 구성은 변하지 않아요: snake_case 키워드 인자, 와이어의 별칭. 세 가지 동작이 달라져요.
- 단일 값 리터럴(
type, 고정된role)은 그것의 유일한 합법 값이 기본값이에요; 더 이상 철자하지 않아요. - 스키마 기본값이 있는 필드(텍스트 메시지의
role, 패치의replace)는 없으면 구체화된 기본값이 아니라None으로 파싱돼요. - JSON Patch 연산은 타입화된 연산 모델로 파싱돼요. 와이어 형태는 동일합니다.
검증은 예전처럼 관대하게 유지돼요: 알 수 없는 키는 유지되고, pydantic의 기본 강제(coercion)가 적용됩니다. 엄격한 계약은 SDK 모델이 아니라 스펙의 fixture corpus예요.
JSON Patch 항목을 객체로 읽어요
StateDeltaEvent.delta와 ActivityDeltaEvent.patch의 항목은, 딕셔너리로 이벤트를 구성해도 타입화된 연산 모델이에요. patch["path"]나 patch.get("op") 같은 딕셔너리 읽기를 patch.path와 patch.op로 대체하세요. 와이어로 보내지는 JSON은 변하지 않습니다.
패치 라이브러리나 다른 기존 코드가 딕셔너리가 필요하다면, 각 연산을 model_dump(by_alias=True)로 변환하세요. 별칭을 켜두면 move와 copy 연산의 from 같은 와이어 키를 보존합니다.
from ag_ui.core import StateDeltaEvent
event = StateDeltaEvent(delta=[{"op": "replace", "path": "/count", "value": 1}])
operation = event.delta[0]
assert operation.path == "/count" # Previously: event.delta[0]["path"]
assert operation.op == "replace" # Previously: event.delta[0].get("op")
patches = [operation.model_dump(by_alias=True) for operation in event.delta]
assert patches == [{"op": "replace", "path": "/count", "value": 1}]
이전 SDK 딕셔너리와 1.0 모델을 모두 지원하는 어댑터는 딕셔너리 항목을 그대로 두고, 항목이 모델일 때만 model_dump(by_alias=True)를 호출할 수 있어요.
은퇴
MetadataMixin,ag_ui.core,ag_ui.core.types,ag_ui.core.events에서. 생성된 프로토콜 모델은 이미 메타데이터 필드를 담으므로, 별도 헬퍼는 더 이상 내보내지지 않아요. import를 제거하세요; 그것을 상속했던 커스텀 모델은ag_ui.core.types의ConfiguredBaseModel을 상속하고typing에서Optional을,ag_ui.core에서Metadata를 import해metadata: Optional[Metadata] = None을 선언하세요.THINKING_*이벤트.REASONING_*를 내보내세요. 프로듀서 측 shim은 없어요; TypeScript 클라이언트가 자기 쪽에서 옛 스트림을 번역합니다.- 파트로서의
BinaryInputContent:ContentPart에binary멤버가 없고, 그것을 담은 메시지는RunAgentInput검증에서 거부됩니다. 클래스 자체는ag_ui.core에서 한 릴리스 동안 import 가능하게 남아서(DEPRECATIONS.md 참고), 0.x에 맞춰 쓴 어댑터는 여전히 import되고 레거시 분기는 그냥 실행되지 않아요; SDK는 그것을 절대 구성하지 않습니다. 미디어 파트를 사용하세요.
이름 변경
SubAgentInfo→SubagentInfo;MultiAgentCapabilities.sub_agents→subagents(와이어 키subagents).SubAgentInfo는 한 릴리스 동안 같은 클래스의 별칭으로 내보내지지만, 옛 필드와 와이어 키는 그렇지 않아요.ExecutionCapabilities.max_iterations와max_execution_time은 이제 음수를 거부해요.- 콘텐츠 파트는 방향이 아니라 그것이 무엇인지로 이름 붙여졌어요:
InputContent→ContentPart,TextInputContent→TextPart,ImageInputContent→ImagePart(audio, video, document 동일),InputContentSource→PartSource,InputContentDataSource→DataSource,InputContentUrlSource→UrlSource. 옛 이름은 같은 클래스의 별칭으로ag_ui.core에서 계속 내보내집니다. PartSource에 세 번째 가지인FileSource(type="file")가 있어요: 모델 프로바이더가 이미 업로드된 바이트에 대해 발급한 핸들이에요. 소스 클래스에서 분기하는 코드는 그것을 위한 case가 필요해요. 그것의value를 URL로 취급하지 마세요; 에이전트가 핸들을 프로바이더에 넘길 수 없으면, 모델이 받을 수 없는 어떤 파트든 그렇듯 경고와 함께 파트를 건너뛰세요.ToolMessage.content와ToolCallResultEvent.content는UserMessage.content가 이미 그랬듯Union[str, List[ContentPart]]예요. 도구 결과를str로 취급하던 코드는 먼저 좁혀요. 모든 파트는 선택적id를,TextPart는 미디어 파트가 이미 가졌던 선택적metadata를 가져요.
.NET
.NET SDK는 가장 멀리 뛰어요. 그것이 마지막으로 여전히 프로토콜 타입을 손으로 쓰던 SDK였고, 다른 둘이 이미 가진 기능을 얻기 때문이에요.
생성 모델이 ~60개의 손으로 쓴 클래스를 대체해요
소비자가 보는 표면은 예전에 보던 것에서, 스키마가 은퇴시킨 것을 뺀 것과 같아요: 같은 sealed 클래스, 같은 [JsonPropertyName] 와이어 이름, 쓰기 시 생략되는 없는 멤버. .NET의 인식되지 않은 자료에 대한 허용은 변하지 않아요 — 알 수 없는 속성은 System.Text.Json이 항상 하던 대로 건너뛰어집니다 — 그래서 아무도 거기에 없는 엄격함을 기대하면 안 돼요.
한 가지 동작은 예전보다 더 관대해졌어요: SDK가 모델을 갖지 못한 이벤트 타입은 이제 두 스트림 리더 모두에서 스트림을 끝내는 대신 trace 경고와 함께 건너뛰어집니다. 단일 알 수 없는 이벤트를 따로 디코딩하는 것은 여전히 AGUIUnknownEventTypeException을 던져요.
서브에이전트
SUBAGENT_STARTED, SUBAGENT_FINISHED, SUBAGENT_ERROR에는 모델, JSON 처리, protobuf 매퍼가 있어요. SubagentRunId는 귀속을 담을 수 있는 이벤트의 속성입니다 — 기본 이벤트가 아니라 — 그래서 이벤트 타입으로 분기하는 소비자는 그것을 구체 타입에서 읽어요. subagent rules가 소비자가 그것으로 무엇을 해야 하는지 말해 줘요.
은퇴
AGUIBinaryInputContent, 그것의 타입 상수, 그 변환기 가지들. Microsoft.Extensions.AI 경계를 건너는DataContent나UriContent는 그것의 미디어 타입이 지칭하는 미디어 파트가 되고, 파일 이름은 파트의 메타데이터에 있습니다. .NET에는 미들웨어 레이어가 없고 들어오는 레거시 파트를 번역하는 것도 없어요:{ "type": "binary" }파트는 알 수 없는 판별자이고, 변환기는 전체 메시지 — 그리고 그것을 담은 스냅샷이나 실행 입력 — 의 역직렬화를 실패시키는JsonException을 던져요. 여전히 레거시 파트를 내보내는 프로듀서는 1.0 .NET 소비자가 그것을 읽기 전에 업그레이드되어야 해요.
이름 변경과 타입 변경
SubAgentInfo→SubagentInfo;MultiAgentCapabilities.SubAgents→Subagents(와이어 키subagents). 별칭이 없어요; 옛 키는 건너뛰어집니다.AgentCapabilities.Custom과IdentityCapabilities.Metadata는IDictionary<string, object?>?가 아니라JsonElement?예요.JsonSerializer.SerializeToElement(...)로 그것들을 구성하세요.ExecutionCapabilities.MaxIterations과MaxExecutionTime은int?가 아니라long?이에요.Tool.Parameters와RunAgentInput.ForwardedProperties(와이어 키forwardedProps)는 스키마가 말하는 대로 nullableJsonElement?이고, 메시지의Id는 항상 쓰이는 비-nullable 문자열이에요.AGUIUserContent→AGUIContent: 문자열-또는-파트 유니언은 더 이상 사용자 메시지 전용이 아니에요.AGUIToolMessage.Content와ToolCallResultEvent.Content는string이 아니라AGUIContent예요; 문자열은 여전히 암묵적으로 할당되고, 다시 읽는 것은Content.Value as string또는 그것의 파트를 훑는 것입니다. 파트 클래스는 스키마가 그것들을...Part로 이름 바꿨더라도AGUI...InputContent이름을 유지해요. 모든 파트는 선택적Id를,AGUITextInputContent는 미디어 파트가 이미 가졌던 선택적Metadata를 가져요.AGUIInputContentSource에 세 번째 하위 클래스AGUIInputContentFileSource(type: "file", 상수AGUIInputContentSourceTypes.File)가 있어요: 모델 프로바이더가 이미 업로드된 바이트에 대해 발급한 핸들로, 선택적Provider와MimeType을 가집니다. 소스 계층 위의switch는 그것을 위한 case가 필요해요. 그것의Value를 URL로 취급하지 마세요; 에이전트가 핸들을 프로바이더에 넘길 수 없으면, 모델이 받을 수 없는 어떤 파트든 그렇듯 경고와 함께 파트를 건너뛰세요.
AOT
소스 생성 직렬화 컨텍스트는 사전 컴파일(ahead-of-time compilation) 아래서 유일한 리졸버예요. 도구 결과는 그것의 런타임 타입으로 직렬화되고, 컨텍스트가 등록하지 않은 타입의 결과는 NotSupportedException을 던져요. int는 1.0에서 명시적으로 등록되며 — 이전에는 우연히만 존재했어요.
다음에 볼 곳
- 프로토콜 레벨 차이에 대한 Key Changes 페이지, 스펙으로의 링크 포함.
- 이제 스펙화됐을 때 선언이 무엇을 의무화하는지 Capabilities.
- 1.0 피어가 옛 피어와 어떻게 대화하는지 Versioning and compatibility.
더 알아보기 (Learn more)
- 스펙 (Specification) — AG-UI 1.0 프로토콜의 공식 요구사항을 확인해 보세요.
- Key Changes — 1.0에서 바뀐 프로토콜 목록을 살펴보세요.