Agent — Declarative와 BYO
Agent는 작성 방식이 둘이다. Declarative는 지시문·모델·tool을 YAML에 적으면 kagent runtime이 실행하고, BYO는 우리가 만든 container image를 kagent가 배포만 한다.- Declarative Agent의 능력은
tools에 적은 tool 이름으로 정해진다. 적지 않은 tool은 쓸 수 없다. - BYO image는
8080포트에서 A2A 서버로 응답해야 한다. 그 밖의 내부 구현은 kagent가 관여하지 않는다. - 위험한 tool은
requireApproval에 넣어 실행 전에 사람의 승인을 받게 한다.
이 장에서 처음 나오는 말5개
Declarative Agent- 지시문·모델·tool을 리소스에 적기만 하면 kagent가 준비한 runtime image가 실행하는 Agent다. 코드를 쓰지 않는다.
BYOBring Your Own- LangGraph·CrewAI·ADK 등으로 직접 만든 Agent를 container image로 가져오는 방식이다.
system message- Agent의 역할과 행동 규칙을 적은 지시문이다. 모든 대화의 맨 앞에 붙어 모델에 전달된다.
HITLHuman-in-the-Loop- Agent가 tool을 실행하기 전에 멈추고 사람의 승인이나 답을 기다리는 방식이다.
Agent Card- A2A에서 Agent가 자기 이름·설명·skill을 알리는 JSON 문서다. 호출하는 쪽이 먼저 읽는다.
큰 그림에서 Agent 리소스 하나가 Deployment와 호출 주소가 된다는 것을 봤다.
이 페이지는 그 리소스 안에 무엇을 적는지를 본다. 읽고 나면 “이 Agent를 Declarative로 만들지 BYO로 만들지”와
“manifest의 어느 필드가 Agent의 능력을 정하는지”에 답할 수 있다.
두 작성 방식
섹션 제목: “두 작성 방식”같은 Agent kind지만 spec.type에 따라 kagent가 맡는 범위가 다르다
(API reference).
| Declarative | BYO | |
|---|---|---|
| 우리가 주는 것 | 지시문·모델·tool 목록 (YAML) | container image |
| 대화 loop를 돌리는 것 | kagent의 ADK runtime image | 우리 코드 |
| 모델 연결 | ModelConfig 참조 | image 안에서 직접. env로 key 주입 |
| tool 연결 | tools에 선언. kagent가 주입 | image 안에서 직접 |
| kagent가 해 주는 것 | 배포 + 실행 + session 저장 + HITL | 배포 + A2A 중계 |
| 맞는 경우 | 지시문과 tool 조합으로 충분한 업무 Agent | 분기·상태·외부 연동이 복잡해 코드가 필요한 Agent |
판단 기준은 단순하다. YAML로 표현되면 Declarative, 안 되면 BYO다. Declarative가 리뷰하기 쉽다 — PR의 diff가 곧 Agent가 할 수 있는 일의 변화다. BYO는 image 안을 봐야 한다.
Declarative Agent의 모양
섹션 제목: “Declarative Agent의 모양”# 설명용 예제apiVersion: kagent.dev/v1alpha2kind: Agentmetadata: name: hr-helper namespace: agentsspec: description: 휴가·근태 규정을 안내하고 본인 신청 내역을 조회한다 type: Declarative declarative: runtime: go modelConfig: litellm-default systemMessage: | 너는 인사 규정을 안내하는 Agent다. 조회 tool의 결과에 없는 내용은 추측하지 않는다. tools: - type: McpServer mcpServer: name: portal-api-mcp kind: MCPServer toolNames: - get_my_leave_requests네 덩어리로 읽는다.
| 필드 | 뜻 | 자세히 |
|---|---|---|
runtime | Agent Pod가 쓸 ADK 구현. go 또는 python | 아래 runtime 절 |
modelConfig | 같은 namespace의 ModelConfig 이름. 생략하면 default-model-config | ModelConfig |
systemMessage | 지시문. systemMessageFrom으로 ConfigMap에서 읽을 수도 있다 | 아래 지시문 절 |
tools | 쓸 수 있는 tool 서버와 tool 이름. 최대 20개 | Tool 연결 |
지시문은 조각으로 재사용할 수 있다
섹션 제목: “지시문은 조각으로 재사용할 수 있다”여러 Agent가 같은 안전 규칙을 지시문에 복사해 넣으면 규칙을 바꿀 때 전부 고쳐야 한다.
prompt template은 공통 조각을 ConfigMap에
한 번 두고 {{include "별칭/key"}}로 끌어온다. controller가 배포 시점에 조각을 펼쳐서 넣는다.
# 발췌declarative: promptTemplate: dataSources: - kind: ConfigMap name: company-prompts alias: company systemMessage: | 너는 {{.AgentName}}이다. {{include "company/safety-rules"}}Secret은 참조할 수 없다. 지시문은 모델 provider로 전송되므로 비밀 값이 섞이지 않게 막은 것이다.
runtime은 Go가 기본이다
섹션 제목: “runtime은 Go가 기본이다”Declarative Agent의 runtime은 둘이고 v0.10부터 Go가 기본이다.
| Go ADK | Python ADK | |
|---|---|---|
| 시작 시간 | 약 2초 | 약 15초 |
| 자원 사용 | 낮다 | 높다 |
| 채팅 파일 첨부 | 지원 | 미지원 |
| 고를 때 | 기본. 빠른 시작과 낮은 비용 | CrewAI·LangGraph 등 Python 생태계 기능이 필요할 때 |
기본값은 버전에 따라 바뀐 적이 있으므로 manifest에 runtime을 명시한다. PR에서 의도가 보이고,
업그레이드 때 runtime이 조용히 바뀌지 않는다.
Deployment 설정도 같은 리소스에 적는다
섹션 제목: “Deployment 설정도 같은 리소스에 적는다”자원 요청, 환경 변수, annotation은 spec.declarative.deployment에 적는다
(Deployment configuration).
# 발췌declarative: deployment: env: - name: LOG_LEVEL value: info deploymentAnnotations: argocd.argoproj.io/sync-wave: "5"annotations는 Pod template에, deploymentAnnotations는 Deployment 자체에 붙는다. Argo CD의 sync-wave처럼
GitOps 도구가 읽는 값은 뒤쪽에 둔다.
BYO Agent의 모양
섹션 제목: “BYO Agent의 모양”BYO는 image와 환경 변수만 적는다. BYO 예제의 형태다.
# 설명용 예제apiVersion: kagent.dev/v1alpha2kind: Agentmetadata: name: contract-reviewer namespace: agentsspec: description: 계약서 초안을 조항별로 검토한다 type: BYO byo: deployment: image: registry.example.com/agents/contract-reviewer@sha256:... imagePullSecrets: - name: registry-credentials env: - name: OPENAI_API_KEY valueFrom: secretKeyRef: name: litellm-agent-key key: api-keykagent가 image에 기대하는 것은 하나다 — 8080 포트에서 A2A 프로토콜로 응답할 것
(API reference). 그러면 controller가
Declarative Agent와 같은 주소(/api/a2a/{namespace}/{name}/)로 중계한다.
BYO에서는 tools·modelConfig를 kagent가 주입하지 않는다. tool 연결은 image 안의 코드가 직접 하고,
임직원 토큰 전파도 Declarative와 방법이 다르다. project를 만들고 로컬에서
시험하는 순서는 BYO Agent 로컬 개발 흐름에서 다룬다.
BYO Agent가 쓰는 tool은 리소스에 없다
섹션 제목: “BYO Agent가 쓰는 tool은 리소스에 없다”BYOAgentSpec의 필드는 deployment 하나뿐이다
(API reference). tools나 toolNames를
적는 자리가 없어서, Agent 리소스만 봐서는 이 Agent가 어떤 tool을 쓰는지 알 수 없다. Declarative처럼
tool 이름 단위의 allowlist를 manifest에 걸 수도 없다.
kagent 밖에서 알아내거나 제한하는 방법은 다음과 같다.
| 방법 | 알 수 있는 것 | 한계 |
|---|---|---|
| source 저장소 리뷰 | 코드가 연결하는 MCP 서버와 고른 tool. kagent init으로 만든 project라면 kagent.yaml의 MCP 서버 목록과 agent.py의 tool filter | image가 그 commit에서 만들어졌다는 보장이 따로 필요하다(digest 고정, build 주체 통제) |
manifest의 env·Secret 참조 | 어떤 자격을 쥐고 있는가 | 그 자격으로 무엇을 하는지는 보이지 않는다 |
| NetworkPolicy의 egress | Pod가 닿을 수 있는 목적지 | 아는 것이 아니라 제한하는 것이다. 허용된 서버 안에서 어떤 tool을 부르는지는 모른다 |
| MCP 서버·backend의 로그 | 실제로 호출된 tool과 호출자 | 사후 확인이고 우리가 운영하는 서버에 한한다 |
| Agent Card | Agent가 스스로 밝힌 skill | 자기 신고라 실제 코드와 다를 수 있다 |
실제로 통제가 되는 것은 둘이다. 닿을 수 있는 MCP 서버를 egress로 제한해 tool의 상한을 정하고, 각 MCP 서버가 호출자를 확인한다. 그래서 GitOps PR 승인에서 BYO Agent는 Declarative보다 높은 위험 등급으로 다룬다 — 리뷰 대상이 manifest의 diff가 아니라 source와 image의 출처다.
Agent가 멈추고 사람을 기다리는 경우
섹션 제목: “Agent가 멈추고 사람을 기다리는 경우”Agent가 삭제·변경 tool을 스스로 실행하면 지시문의 실수 하나가 실제 사고가 된다. HITL은 두 가지로 사람을 끼워 넣는다.
- tool 승인:
requireApproval에 적은 tool은 실행 전에 멈추고 승인·거절을 기다린다. 거절 사유는 모델에 전달되어 다른 방법을 찾게 한다. ask_user: 모든 Agent에 자동으로 붙는 내장 tool이다. 요청이 모호하면 Agent가 사용자에게 되묻는다.
# 발췌 — 조회는 바로, 신청은 승인 뒤에tools: - type: McpServer mcpServer: name: portal-api-mcp kind: MCPServer toolNames: - get_my_leave_requests - create_leave_request requireApproval: - create_leave_requestrequireApproval의 이름은 toolNames에도 있어야 한다. 승인 화면은 kagent UI가 제공하지만, 우리 portal에서
Agent를 호출한다면 A2A 응답의 input-required 상태를 portal이 받아 승인 UI를 직접 그려야 한다.
그 밖의 기능
섹션 제목: “그 밖의 기능”지금 결정에 필요하지 않으면 이름과 쓸 때만 알아 둔다.
| 기능 | 무엇인가 | 언제 필요한가 |
|---|---|---|
| Skills | OCI image·Git·S3에서 지침과 script를 불러와 Agent에 붙인다 | 사내 runbook을 여러 Agent가 공유할 때 |
| Memory | 대화에서 뽑은 정보를 vector로 저장해 다음 대화에서 찾는다 | 대화를 넘어 기억해야 할 때. pgvector가 필요하다 |
| Context compaction | 오래된 대화를 요약하거나 버려 context window를 지킨다 | 대화가 길거나 tool 출력이 클 때 |
a2aConfig.skills | Agent Card에 실리는 능력 설명. 실행 코드가 아니다 | 다른 Agent나 client가 이 Agent를 찾게 할 때 |
| Agent Card metadata | version·iconUrl·provider 등을 Agent Card에 싣는다 | catalog에 버전·소유 조직을 표시할 때 |
상태 확인
섹션 제목: “상태 확인”배포 결과는 리소스의 condition으로 본다. 첫 MCP tool 문서의
출력 예처럼 두 condition이 순서대로 True가 된다.
| condition | True의 뜻 | False일 때 먼저 볼 것 |
|---|---|---|
Accepted | controller가 spec을 받아들였고 참조를 풀었다 | ModelConfig·tool 서버 이름과 namespace, tool 이름 오타 |
Ready | Deployment의 Pod가 준비됐다 | image pull, Secret 누락, Pod 로그 |
kubectl -n agents get agent hr-helper -o jsonpath='{.status.conditions}'이해 확인
섹션 제목: “이해 확인”- Declarative Agent의
toolNames에서 tool 하나를 지운 PR이 merge되면 무엇이 바뀌는가? → controller가 Agent Pod의 설정을 다시 만들고, 그 Agent는 지운 tool을 더는 호출할 수 없다. MCP 서버 자체는 그대로다. - BYO Agent의 manifest만 보고 이 Agent가 어떤 tool을 쓰는지 알 수 있는가? → 알 수 없다. image 안의 코드가 정하므로 source repo를 봐야 한다. 이것이 BYO의 리뷰 비용이다.