콘텐츠로 이동

Registry 기반 에이전트 구성

Terminal window
uv run llamon agent my-agent --template agent-general --yes
템플릿잘 맞는 작업출력
agent-general대화, 검색, 도구 호출자연어 중심
agent-structured분류, 추출, 판정Pydantic으로 검증한 DataPart
data-summary기존 DataPart 요약response contract 기반 WorkHistory summary
outcome-evaluatorORCH 임시 후보 검증verification decision DataPart 정확히 하나

처음에는 agent-general로 시작해도 충분합니다. 다음 에이전트나 프로그램이 안정된 JSON을 읽어야 하면 agent-structured, 기존 DataPart를 요약하려면 data-summary를 고르세요. outcome-evaluator는 일반 판정 에이전트가 아니라 ORCH 결과 검증 루프에서만 쓰는 opt-in producer입니다.

파일역할수정 시점
app/config.pyLLM·Prompt·Guardrail·MCP·하위 Agent 설정구성 요소를 연결할 때
app/agent_card.py이름, 설명, 스킬, 공개 기능외부에 보일 계약을 바꿀 때
.envRegistry 주소, 공개 URL, 비밀값배포 환경마다
app/runtime_adapter.py구조화 출력과 후처리agent-structured 또는 고급 변환이 필요할 때
app/evaluator_policy.pyevaluator version·baseline·seed rendereroutcome-evaluator 기준을 버전업할 때
prompts/outcome-evaluator-system-prompt.template.mdRegistry prompt 본문evaluator 지시문을 수정할 때

생성된 main.py는 조립 진입점입니다. 특별한 서버 정책을 켜지 않는 한 손댈 필요가 없습니다.

Registry 구성 요소는 이름이 아니라 ID로 연결합니다.

app/config.py
from llamon_agent.config import ExtensionConfig, LLMConfig, PromptConfig, PromptSetConfig
def build_extension(max_retry: int = 3) -> ExtensionConfig:
return ExtensionConfig(
llm=LLMConfig(id="<YOUR_MODEL_ID>", temperature=0.1),
prompts=PromptSetConfig(
system=PromptConfig(id="<YOUR_PROMPT_ID>"),
),
max_retry=max_retry,
)

필요한 기능만 ExtensionConfig에 더합니다.

필드용도기본 원칙
guardrails입력·출력 검사실제 정책이 있을 때만 연결
mcpLLM이 선택하는 도구확정 호출은 deterministic_tool 사용
agent하위 A2A 에이전트DataPart·FilePart 전달은 명시적으로 허용
artifact_name·artifact_description응답 artifact 식별고정 이름이 필요할 때 설정
multi_skill_merge여러 스킬 결과 병합기본 concat; 경쟁 후보만 judge

방향별 정책은 다음처럼 설정합니다. mode="stream"은 output 전용입니다.

from llamon_agent.config import GuardrailConfig, GuardrailSetConfig
guardrails = GuardrailSetConfig(
input=GuardrailConfig.ref("input-policy"),
output=GuardrailConfig.ref(
"output-policy",
mode="stream",
pii_action="mask",
),
)

일반 Agent도 같은 설정을 지원합니다. 입력 mask를 명시하지 않으면 원본 text·DataPart·FilePart를 보존합니다.

Registry 프롬프트의 {{변수}}VariableBindingConfig로 채웁니다.

from llamon_agent.config import PromptConfig, VariableBindingConfig
PromptConfig(
id="<YOUR_PROMPT_ID>",
bindings={
"job": VariableBindingConfig(source="input"),
"user": VariableBindingConfig(source="context.userId", default="anonymous"),
"tenant": VariableBindingConfig(source="env.LLAMON_TENANT", default="default"),
},
)
source읽는 값
input사용자 입력 텍스트
context.<key>요청 metadata. state.metadata.<key>와 같은 값
env.<VAR>LLAMON_·PROMPT_·TMPL_로 시작하는 환경변수
const.<value>고정 문자열

dictlist는 기본적으로 JSON 문자열로 렌더링됩니다. json, join_newline, bool_presence, response_contract_facts 같은 transform이 필요하면 해당 바인딩에만 지정하세요. response_contract_facts는 DataPart를 계약에 맞는 사실로 줄이는 기능이며 검색 지식과는 별개입니다. 자세한 계약 작성법은 응답 계약을 참고하세요.

LLM 튜닝 파라미터 — reasoning · 출력 분량 · provider_extra

섹션 제목: “LLM 튜닝 파라미터 — reasoning · 출력 분량 · provider_extra”

공통 옵션은 LLMConfig에 두고 제공자 전용 값만 provider_extra로 보냅니다.

LLMConfig(
id="<YOUR_MODEL_ID>",
max_tokens=1024,
reasoning="low",
provider_extra={"repetition_penalty": 1.05},
)

provider_extra는 SDK 변환값보다 우선하므로 꼭 필요한 키만 넣으세요. 같은 모델이라도 vLLM, 공식 API, Ollama /v1이 받는 필드는 다릅니다.

Reasoning 입력 형태와 Reasoning 필드

섹션 제목: “Reasoning 입력 형태와 Reasoning 필드”
형태의미
boolreasoning=False추론 기능 켜기·끄기
strreasoning="high"추론 강도 지정
dict{"effort":"high","summary":"auto"}여러 필드 동시 지정
ReasoningReasoning(budget_tokens=2048)내부 추론 예산 지정

enabled=Falseeffort·budget_tokens·summary와 함께 쓸 수 없습니다. effortbudget_tokens도 둘 중 하나만 선택합니다. 제공자별 오류는 reasoning 문제 해결에서 확인하세요.

여러 스킬이 서로 다른 일을 한다면 기본 concat이 맞습니다. 같은 질문에 답하는 후보 가운데 하나만 고를 때만 judge를 켭니다.

from llamon_agent.config import JudgeLLMConfig, MultiSkillMergeConfig
multi_skill_merge=MultiSkillMergeConfig(
mode="judge",
judge_llm=JudgeLLMConfig(id="<YOUR_JUDGE_MODEL_ID>"),
)

judge_llm을 생략하면 주 LLM을 재사용합니다. 후보가 하나뿐이거나 판정 호출이 실패하면 기존 concat으로 돌아갑니다. 상보적인 결과에 judge를 적용하면 judge가 필요한 출력을 조용히 버릴 수 있으므로 경쟁 후보에만 사용하세요. 코드 중심 Flow에서는 flow.judge_panel()이 같은 순위 판정기를 사용합니다. judge 모드는 실행할 때마다 LLM을 한 번 더 호출합니다.

설정은 수명주기에 따라 나누면 찾기 쉽습니다.

위치담는 값
nodes.pyRuntimeEnv(source_file=__file__)한 노드에서만 쓰는 환경값
config.py여러 노드가 공유하는 ID·이름·라벨·기본값
.env배포별 실제 값과 비밀값

POSTGRES_URL, API 키, 토큰을 config.py에 직접 적지 마세요. Studio의 승급·강등 제안은 공유 횟수를 기준으로 위치를 추천합니다. 적용 전 변경 내역을 확인할 수 있습니다. 쓰기에 실패하면 전체 변경을 되돌립니다.

app/agent_card.py에서는 카드 설명과 스킬을 다듬습니다. 스킬이 여러 개면 nametags가 사전 라우팅에 쓰이므로 사용자가 입력할 법한 표현을 짧게 넣는 편이 좋습니다.

app/agent_card.py
from llamon_agent.config import Settings, resolve_agent_card_url
from llamon_agent.server import AgentCardBuilder
def build_card(settings: Settings):
return (
AgentCardBuilder(
name="my-agent",
description="주문 상태를 조회하고 요약합니다",
url=resolve_agent_card_url(settings),
version="1.0.0",
)
.add_skill(
id="order-lookup",
name="주문 조회",
description="주문 번호로 배송 상태를 조회합니다",
tags=["order", "lookup"],
examples=["주문 12345 지금 어디쯤이야?"],
)
.set_capability_metadata(
output_schemas=["my-agent.output.v1"],
capabilities=["order_lookup"],
)
.set_capabilities(streaming=True, push_notifications=False)
.build()
)

resolve_agent_card_url()PUBLIC_AGENT_URL이 있으면 그 값을, 없으면 AGENT_URL을 씁니다. set_capability_metadata()는 오케스트레이터 라우팅·카탈로그가 읽는 선언이며 응답 payload를 바꾸지 않습니다.

.env에서 먼저 확인할 값은 다음과 같습니다.

LLAMON_REGISTRY_HOST=http://<registry-host>:7860
AGENT_ID=<registry-agent-id>
PUBLIC_AGENT_URL=http://<proxy-host>:<port><a2a-path>
HOST=0.0.0.0
PORT=8000

AGENT_ID와 Registry의 Agent ID는 같아야 합니다. PUBLIC_AGENT_URL의 경로도 Registry UI에 표시된 A2A 경로와 맞추세요. 운영 배포에서는 생성본의 예시 호스트를 실제 프록시 주소로 바꿉니다.

Pydantic 스키마 하나로 검증까지 맡기기 (SchemaValidatedRuntimeAdapter)

섹션 제목: “Pydantic 스키마 하나로 검증까지 맡기기 (SchemaValidatedRuntimeAdapter)”

agent-structured에서는 Pydantic 모델 하나로 LLM 출력의 파싱과 검증을 맡길 수 있습니다.

app/runtime_adapter.py
from typing import Literal
from pydantic import BaseModel, Field
from llamon_agent import SchemaValidatedRuntimeAdapter
class IntentPayload(BaseModel):
intent: Literal["simple", "document", "unknown"]
confidence: float = Field(ge=0, le=1)
class MyAgent(SchemaValidatedRuntimeAdapter[IntentPayload]):
payload_schema = IntentPayload
def apply_business_rules(self, payload, *, query, a2a_files, **_):
if a2a_files:
payload.intent = "document"
return payload
def format_summary(self, payload):
return f"{payload.intent}로 분류했습니다."

payload는 요청 DataPart가 아니라 검증을 마친 LLM 출력입니다. 원본 요청은 query, a2a_files, a2a_data로 받습니다. 검증 실패 시 기본 안전 응답을 쓰거나 on_validation_error()를 재정의하세요. 동적 dict나 다단계 호출이 필요하면 RuntimeAdapter 고급으로 넘어갑니다.

응답에 이름과 설명 붙이기 (artifact_name / artifact_description)

섹션 제목: “응답에 이름과 설명 붙이기 (artifact_name / artifact_description)”

고정 metadata는 ExtensionConfig에 둡니다. 요청마다 이름이 달라질 때만 RuntimeOutput이나 graph의 최종 output에서 덮어쓰세요.

우선순위는 요청 결과값 → Adapter ClassVar → ExtensionConfig → SDK 기본 이름 순입니다. 신규 프로젝트에서 이름만 바꾸려고 runtime_adapter.py를 만들 필요는 없습니다.

개발용 Ollama나 직접 관리하는 OpenAI 호환 엔드포인트는 --runtime-source local로 생성합니다. Registry 정책과 중앙 배포가 필요한 운영 에이전트에는 맞지 않지만 로컬 실험과 코드 중심 구성에는 유용합니다. 설정과 빠른 시작은 직접 모델 연결에 남겨 두었습니다.

Registry 없이도 deterministic 개인정보 탐지와 kind별 부분 마스킹을 적용할 수 있습니다. 설정 방법과 출력 형태는 개인정보 마스킹을 참고하세요.