엑셀에 담긴 지표를 읽어 분석 문장을 붙이고 Word 보고서로 떨어뜨리는 워크플로다. 매일 같은 형식으로 나와야 하고, 숫자를 틀리면 안 된다.
사용자 엑셀
-> Excel Report Reader Tool 정확한 셀 값 읽기 · 영역 구조화 · 객관적 파생지표 계산
-> Agent KPI 선정 · 변화 비교 · 인사이트 도출 · 보고서 내용 구성
-> Word Report Tool KPI · 요약 · 차트 · 상세표를 정해진 양식으로 배치
-> 보고서.docx
정확성이 요구되는 일은 Tool 에, 정답이 하나가 아닌 판단은 Agent 에 둔다. 이 경계가 흐려지면 품질이 매번 달라진다.
| 단계 | 담당 | 이유 |
|---|---|---|
| 엑셀 파일 읽기 | Tool | 실제 셀 값에 접근해야 한다 |
| 데이터 구조화 · 파생지표 계산 | Tool | 행·열 위치와 지표를 정확히 연결하고, 계산 가능한 값은 일관되게 제공해야 한다 |
| 주요 지표 선정 | Agent | 무엇을 강조할지는 전체를 비교해 정해야 한다 |
| 지표 해석과 설명 | Agent | 목표 대비 · 전일 대비 · 전년 대비를 종합해야 한다 |
| 보고서 내용 구성 | Agent | 강조할 내용과 서술 방식에 정답이 없다 |
| Word 파일 생성 | Tool | 양식 · 표 · 차트 · 파일 형식을 일관되게 만들어야 한다 |
Reader Tool 이 단순 읽기만 하는 것이 아니라 열 위치에 지표 의미를 부여하고(metric_schema) 파생값까지 계산해(derived_metrics) 넘기는 것이 핵심이다. 계산을 Agent 에 맡기면 실행마다 값이 흔들린다.
보고서를 영역(섹션)별로 쪼개고, Task 하나가 영역 하나만 다루게 한다. 로직은 같고 두 값만 바뀐다.
| Task | section_name |
output_filename |
|---|---|---|
| Task 1 - <영역1> 분석 | <영역1> |
daily_report_01.docx |
| Task 2 - <영역2> 분석 | <영역2> |
daily_report_02.docx |
| Task 3 - <영역3> 분석 | <영역3> |
daily_report_03.docx |
| Task 4 - <영역4> 분석 | <영역4> |
daily_report_04.docx |
공통 템플릿을 하나 두고 두 값만 치환한다.
{Attachments} 로 제공된 Excel 파일에서 현재 Task 의 대상 영역을 분석한다.
1. Excel Report Reader Tool 을 정확히 한 번 호출한다.
- sheet_name: "Report"
- section_name: "{SECTION_NAME}"
- compact_output: true
- include_formulas: false
2. Reader Tool 이 반환한 현재 section 데이터만 사용한다.
다른 section 이나 이전 Task 의 분석 결과는 사용하지 않는다.
metric_schema 로 지표의 의미를 확인하고 각 row 의 metrics 와
derived_metrics 를 분석 근거로 사용한다.
서로 다른 row_id 의 값을 임의로 결합하거나 상위·하위 항목을 중복 합산하지 않는다.
3. 단순 수치 나열이 아닌 종합적인 인사이트를 작성한다.
데이터에 존재하지 않는 사실이나 원인은 추측하지 않는다.
4. Word Report Tool 을 정확히 한 번 호출한다.
- output_filename: "{OUTPUT_FILENAME}"
Tool 이 success=true 및 artifact_created=true 를 반환하면 종료한다.
다른 section 이나 이전 Task 의 분석 결과는 사용하지 않는다 한 줄이 실제로 효과가 크다. 이것이 없으면 앞 Task 에서 읽은 수치가 뒤 Task 의 서술에 섞여 들어간다.
Task 이름도 Task 1 - <영역> 분석 처럼 고정한다. 실행 로그에서 어느 단계가 실패했는지 바로 보인다.
Agent 의 Goal 과 주의 사항에 다음을 명시한다. 문장을 막연하게 "정확하게 쓰라" 고 적는 것으로는 막히지 않는다. 금지할 표현과 허용할 표현을 목록으로 준다.
수치와 항목명을 연결할 때 반드시 동일한 row_id 의 값만 사용한다.
한 항목을 설명하면서 다른 row_id 의 목표·실적·진척률·연간 값을 가져와 연결하지 않는다.
상위 항목과 하위 항목의 이름이 비슷하더라도 서로 다른 row_id 의 수치를 섞지 않는다.
기여도나 영향도가 데이터로 계산되지 않았다면 인과를 쓰지 않는다.
| 쓰지 않는 표현 | 대신 쓰는 표현 |
|---|---|
| 견인 · 상쇄 · 영향을 미침 | 상대적으로 높은 수준을 보임 |
| 원인이 됨 · 기여함 | 기준 대비 낮은 수준임 |
| 이탈로 인해 · ~때문에 증가 | 두 지표가 동시에 증가함 |
| ~도입 이후 개선 | 서로 상반된 흐름을 보임 · 추가 확인이 필요함 |
수치의 단위는 Tool 데이터에서 확인되는 단위만 사용한다.
확인할 수 없으면 "원", "억원", "건", "명" 등을 임의로 붙이지 않는다.
상위·하위 항목의 합계 관계가 데이터에서 확인되지 않으면
"구성", "비중", "점유율", "구성비" 로 표현하지 않는다.
이 경우 "항목별 실적 비교", "항목별 진척률 비교" 처럼 단순 비교로 쓴다.
하위 항목의 합이 상위 항목과 맞지 않거나 중복 여부를 알 수 없는데 비중으로 서술하면, 읽는 사람이 숫자를 잘못 해석한다. 이것이 실무에서 가장 많이 나오는 사고다.
지표의 방향성이 데이터에서 명확하지 않으면
높음/낮음, 양호/부진, 안정/위험 같은 평가를 하지 않는다.
현재 값, 기준 대비 차이, 변화만 객관적으로 설명한다.
잔액처럼 늘어나는 것이 좋은지 나쁜지가 문맥에 달린 지표를 "실적" 으로 묶으면 Agent 가 임의로 좋고 나쁨을 붙인다. Goal 문구에서 실적 같은 편향된 단어를 지표 로 중립화해 두면 이 문제가 줄어든다.
항목명이 길거나 한글이면 차트 축 라벨이 잘리거나 깨진다. 폰트를 바꾸는 것보다 차트에는 번호만 넣고 바로 아래 표에서 번호와 항목명을 잇는 방식이 안정적이다.
1 █████ 100.7
2 █████ 102.1
3 █████ 106.8
4 ██████ 122.5
1 -> (글로벌) 장기대출
2 -> (결제) 장기대출
3 -> (결제) 차량할부(R064)
4 -> (결제) 차량할부(R065)
엑셀이 계층 구조라 가장 깊은 라벨이 코드값인 경우가 있다.
카드 취급액 > 신판 > 55
Reader 가 path[-1] 을 그대로 item_name 으로 쓰면 Agent 에게 item_name = "55" 가 전달되고, 보고서에 '55' 항목의 진척률은... 이라고 찍힌다.
이것은 Task 프롬프트로 막을 문제가 아니라 Reader 에서 고칠 문제다. "숫자 항목명을 쓰지 마라" 고 적어도 Agent 에게는 그 숫자밖에 없다.
import re
from typing import List
def is_code_like_label(value: str) -> bool:
text = (value or "").strip()
if not text:
return False
return bool(re.fullmatch(r"\d+", text))
def build_item_name(path: List[str], row_id: str) -> str:
if not path:
return row_id
leaf = path[-1]
# 마지막 라벨이 단순 코드·숫자면 상위 항목을 붙여 의미를 남긴다
if is_code_like_label(leaf) and len(path) >= 2:
return f"{path[-2]} ({leaf})"
return leaf
path = ["카드 취급액", "신판", "55"] -> item_name = "신판 (55)"
정확히 한 번 호출한다, 성공하면 같은 Tool 을 다시 호출하지 않는다. 같은 Tool 이 반복 호출된다면 파라미터가 매번 같아 진행이 없는 구조인지 먼저 본다.Artifact 생성 여부와 파일명만 간결하게 반환한다 를 명시한다.report_title 을 파라미터로 넘기거나, 보고서 제목과 구성은 다른 section 보고서와 동일한 형식을 사용한다 를 명시한다.모델이나 데이터를 단계별로 반입할 때, 진행 표의 빈칸은 "아직 안 한 것" 과 "시도했다 실패한 것" 과 "기술적으로 보류한 것" 을 구분하지 못한다. 기존 표 뒤에 네 칸을 더 둔다.
| 추가 컬럼 | 적는 내용 |
|---|---|
| 진행 상태 | 완료 · 검증중 · 보류 · 실패 · 미진행 |
| 이슈 / 미완료 사유 | 실제 발생한 현상 또는 진행하지 못한 이유 |
| 근거 / 확인 내역 | 로그, 공식 문서, 벤더 문의 회신, 내부 테스트 결과 |
| 조치 / 결론 | 해결 방법, 우회 방법, 보류 결정 |
근거 / 확인 내역 을 따로 두는 것이 핵심이다. 나중에 "왜 이건 안 올렸느냐" 는 질문이 왔을 때 담당자의 판단이 아니라 확인된 사실로 답할 수 있다.