에이전트가 HTML이 아닌 데이터를 작성하게 하라
요약
AI 에이전트가 인보이스 같은 문서를 생성할 때, HTML을 직접 작성하게 하는 방식보다 JSON 형태의 구조화된 데이터만 요청하는 것이 실제 운영 환경에 적합합니다. 특히 템플릿과 데이터를 분리하고, 저장된 스키마를 통해 오프라인에서 강력한 검증(validation)을 수행해야 합니다.
핵심 포인트
- HTML 직접 생성보다 JSON 기반 데이터 요청이 안정적입니다.
- 강력한 검증은 사용자가 정의한 스키마에 의존합니다.
- 템플릿과 데이터를 분리하여 구조화된 출력을 확보하세요.
- 단순히 'ok: true'가 반환되어도 데이터의 정확성을 보장하지 않습니다.
AI 에이전트가 인보이스를 생성하는 방법은 두 가지가 있습니다. 첫 번째는 에이전트에게 인보이스 작성을 요청하고, 에이전트가 HTML을 작성하면 그것을 출력하여 PDF 파일로 만드는 방식입니다. 또는 이미 검토된 인보이스 템플릿을 제공하고, 누가(who), 무엇을(what), 몇 개를(how many), 어떤 비율로(at what rate)와 같은 사실 정보만을 JSON 형태로 요청하는 방식이 있습니다.
첫 번째 방법은 데모에서는 작동하지만, 두 번째 방법은 실제 운영 환경에서 살아남는 방식입니다.
문서는 일관성을 약속한다
모델은 샘플링을 통해 작성합니다. 에이전트에게
모델에게 작성할 데이터를 제공한다고 해서 그 데이터가 올바른 것은 아닙니다. 그래서 저희는 짧은 인보이스 템플릿을 가져와 에이전트가 생성하는 경향이 있는 데이터를 validate_template에 입력한 다음, 각 버전을 렌더링했습니다. 이 템플릿 자체를 HTML로 전달했으며, 도구는 MCP 서버 내부에서 이를 오프라인으로 확인합니다:
<table>
{% for line in invoice.lines %}
<tr><td>{{ line.description }}</td><td>{{ line.qty }}</td><td>{{ line.price | money }}</td><td>{{ line.total | money }}</td></tr>
...
데이터가 작성된 대로 검증하자 아무것도 보고하지 않았고, 인보이스는 **Gesamt 3.760,40 €**로 끝납니다. 그리고 에이전트가 생성한 버전들입니다.
에이전트는 라인 총계를 누락합니다. 이는 템플릿이 수량에 가격을 곱할 것이라고 예상했기 때문입니다. 하지만 이 템플릿은 그렇지 않습니다. validate_template는 다음과 같이 응답합니다:
{
"ok": true,
"diagnostics": [
...
그리고 렌더링된 인보이스는 **Gesamt 0,00 €**로 끝납니다.
에이전트는 리스트를 items라고 부릅니다. 이는 스키마를 확인하지 않은 모델에게 lines만큼이나 자연스럽게 들리기 때문입니다. 검증은 다섯 번 경고합니다. 한 번은 invoice.lines에 대해, 그리고 그 아래의 각 필드에 대해 각각 한 번씩 경고하며, 여전히 `
에이전트는 스스로 HTML을 가져오지 않습니다. Formfeed에 저장된 템플릿을 채우는 것이며, 저장된 템플릿의 경우 validate_template은 오프라인에서 검증하지 않습니다. 대신 API에 요청하여 렌더링 없이도 어떤 버전으로 렌더링할지 확인하게 합니다. 이 확인 과정은 데이터를 사용하여 템플릿을 한 번 실행하므로, 위에 나온 "19 %"는 아무것도 출력되기 전에 오류로 반환되며, 데이터와 템플릿에 저장된 JSON Schema를 비교합니다:
{
"severity": "error",
"code": "data-validation",
...
스키마 검사를 위해서는 저장된 스키마가 필요합니다. 모든 템플릿은 샘플 데이터로부터 추론된 스키마를 가지고 있으며, 이것이 get_template_schema가 에이전트에게 전달하는 것이지만, 실제로 무엇이 잘못되었는지를 결정하는 것은 사용자가 저장한 스키마입니다. 추론된 스키마는 샘플에 우연히 포함되어 있던 필드를 누락했을 경우 데이터를 거부할 수 있습니다. 편집기에서 데이터 및 스키마 패널의 Store as contract 기능을 사용하면 하나가 저장되고, CLI를 사용하면 템플릿 옆에 schema.json 파일이 생성됩니다. 에이전트가 채우는 모든 템플릿마다 하나씩 저장하세요.
어느 쪽이든 두 가지 사항을 기억해야 합니다. 첫째, ok: true는 _아무것도 실패하지 않는다_는 뜻이지, _데이터가 옳다_는 의미는 아닙니다. 누락된 데이터는 경고이며, 템플릿은 의도적으로 선택적 필드를 비워둘 수 있기 때문입니다. 에이전트는 모든 경고를 렌더링하기 전에 답해야 할 질문으로 간주해야 합니다. 둘째, 검사는 자신이 들은 것만 압니다. 에이전트를 설정할 때 테스트 키로 연결하세요. 모든 렌더링에 비용이 들지 않으며, 소수의 결과를 읽는 것은 어떤 검증도 할 수 없는 것을 확인합니다. 예를 들어, 올바른 고객이 청구서에 포함되었는지 여부와 같은 것입니다.
위의 오프라인 결과는 MCP 서버 자체 저장소에서 테스트한 결과로, 실제 도구를 네트워크 스텁(network stub)으로 실행하여 모든 요청에서 실패하도록 설정했기 때문에, 또한 임시 HTML과 그 데이터가 검사되는 동안 서버가 구동되는 기계를 벗어나지 않는다는 것을 보여줍니다: validate-agent-data.spec.ts.
에이전트에게 알려야 할 것
MCP 서버는 이미 연결된 에이전트에게 순서(order): 스키마 읽기, 검증(validate), 렌더링(render)을 알려줍니다. 하지만 이 서버가 알 수 없는 것은 사용자의 문서에 얼마나 엄격해야 하는지입니다. 에이전트의 지침에 몇 줄만 추가하면 이 간극을 메울 수 있습니다:
Before rendering a document:
1. Read the template's schema and sample data with get_template_schema, and use the same field names.
2. Call validate_template with your data. Fix every diagnostic, warnings included.
...
모델은 여전히 변경되는 부분만 작성합니다. 절대 바뀌어서는 안 되는 부분은 사람이 한 번 작성한 것이며, 에이전트는 결코 건드릴 수 없습니다.
agents 페이지에는 Claude Code, Cursor, VS Code, Codex 및 수십 개의 클라이언트와 프레임워크 설정이 되어 있으며, MCP 문서에는 모든 도구와 그 인수가 나열되어 있습니다.
2026년 10월 5일 확인됨. validate_template의 스키마 검사는 @formfeed/mcp 0.3.6 이상이 필요합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기