Flocks 자체 배포 사용 경험

5월 1일 휴일 동안 텐센트 클라우드 경량 서버에 Flocks(위버 오픈소스 AgentSecOps 플랫폼)를 배포했으며, 초기 워크플로 생성 실패부터 시작하여 여러 플랫폼 계층 및 LLM 동작 계층의 문제에 직면했습니다. 이 글에서는 과정에서 발생한 문제, 근본 원인, 수정 방식을 정리하여 동일한 요구사항이 있는 사람들을 위해 참고자료로 제공합니다.

환경

  • 텐센트 클라우드 경량 애플리케이션 서버, 2코어 8GB 메모리, 100GB 시스템 디스크
  • Ubuntu 24.04
  • Flocks v2026.4.30, install.sh 자체 배포
  • 모델: Qwen3.6-Plus

작업 목표: Rex가 TDP 취약점 점검 워크플로를 생성하도록 하여 CVE 번호를 입력으로 받고 docx 공문 형식 점검 보고서를 출력하도록 함.

일、write 도구의 오해를 불러일으키는 오류

Rex가 약 12,000자의 workflow.json(JSON 내에 파이썬 코드 조각이 중첩된 이중 구조)을 생성하도록 하고 write 도구를 호출할 때 다음과 같은 오류가 발생했습니다:

Failed to parse tool arguments (12283 chars). 
Please ensure valid JSON with balanced braces/brackets.

오류: Tool not found: invalid

두 가지 오류가 동시에 발생했습니다. 두 번째 오류인 Tool not found: invalid는 도구가 등록되지 않았거나 도구 이름이 잘못되었다고 생각하게 만들었지만, 실제로 도구는 존재했으며 파라미터 구문 분석에 실패한 것뿐이었습니다. 이러한 안내에 오해를 사서 처음에는 JSON 이스케이프 방향으로 문제를 해결하려고 했습니다.

근본 원인: content 필드가 너무 길고(12K+) 이중 이스케이프(외부 JSON + 내부 파이썬 코드 문자열)를 포함하고 있어 LLM이 토큰 스트리밍 생성 중 모든 이스케이프 수준이 올바르다는 것을 보장할 수 없으며, 단 한 곳의 잘못된 위치가 구문 분석 실패를 유발합니다.

대응 방식: AGENTS.md에 규칙을 추가하여 agent가 도구 파라미터로 큰 JSON 문자열을 직접 작성하지 않도록 하고, 대신 json.dumps를 사용하여 라이브러리가 이스케이프를 처리하도록 합니다.

# 잘못된 사용법
tool.run('write', content='{"id":"...", "code":"...대형 중첩..."}')

# 올바른 사용법
workflow = {
    "id": "...",
    "code": '''import re
result = {'k': 'v'}'''   # 삼중 따옴표 + 단일 따옴표, 중첩 회피
}
content = json.dumps(workflow, ensure_ascii=False, indent=2)
tool.run('write', filePath='...', content=content)

이、bash 도구의 command 파라미터 무단 절단

write 도구 실패 후, Rex는 bash + heredoc로 파일 작성을 시도했지만 연속적으로 문제를 겪었습니다:

File "<stdin>", line 275
SyntaxError: unterminated triple-quoted string literal (detected at line 279)

그 다음 python3 -c '...' 내장 중국어 시도:

SyntaxError: bytes can only contain ASCII literal characters

그 다음 여러 번의 echo 추가 시도:

SyntaxError: unterminated triple-quoted string literal (detected at line 239)

실제로 테스트한 결과, bash 도구의 command 파라미터는 약 6KB에서 절단되며 어떠한 오류나 경고도 없습니다 - bash는 절반 잘린 명령어를 직접 실행하여 다양한 SyntaxError를 유발합니다. 이러한 무단 절단은 직접 오류를 보고하는 것보다 디버깅이 더 어렵습니다:

  • 오류 메시지는 완전히 사용자 코드 자체의 구문 오류처럼 보입니다
  • agent는 "코드 수정 → 여전히 오류 → 계속 수정" 루프에 빠지게 됩니다

대응 방식: AGENTS.md에 규칙을 추가하여 "전체 워크플로 재작성" 방식을 금지하고, 대신 read + str_replace를 사용하여 증분 편집을 하며 각각 단일 노드의 차이 부분만 변경하도록 합니다.

삼、Workflow join 필드와 branch 노드의 의미 충돌

워크플로가 WebUI에 로드되면 구조는 정상적입니다:

테스트 실행을 트리거하면 처음 몇 개의 노드는 정상이었지만 마지막에 오류가 발생했습니다:

NodeExecutionError: Join node(s) did not receive all incoming inputs:
generate_report expected=['deep_analysis', 'no_finding_handler']
seen=['no_finding_handler']

generate_report 노드는 "join": true(모든 업스트림 대기)로 구성되어 있으며, 업스트림 deep_analysisno_finding_handlercheck_findings branch의 두 가지 경로입니다. branch는 단일 경로만 따르고, join: true는 모든 경로를 대기하므로 둘은 자연스럽게 충돌합니다.

일반 워크플로 엔진의 의미에 따라 "join": true"join": "any"로 변경했습니다:

1 validation error for Workflow nodes.11.join
Input should be a valid boolean, unable to interpret input 
[type=bool_parsing, input_value='any', input_type=str]

Flocks의 join 필드는 schema 수준에서 true / false 두 가지 bool 값만 허용하며, "any" / "all"과 같은 문자열 값은 지원하지 않습니다. 이것은 문제를 겪기 전에 주목하지 못한 제한 사항입니다 - Flocks의 join 설계는 단순화되어 있지만, schema 수준에서 branch + join: true 조합을 막는 정적 검사는 없습니다.

올바른 방법: branch 후의 합류 노드에서는 "join" 필드를 삭제합니다(join을 작성하지 않음은 false와 동일하며, 업스트림 중 하나가 도달하면 트리거되는 것이 바로 branch 합류에 필요한 의미입니다).

  {
    "id": "generate_report",
    "type": "python",
-   "join": true,
    "code": "..."
  }

이후 워크플로에 새 노드를 추가할 때 이 오류가 다시 한번 발생했습니다:

이는 LLM이 "이전의 교훈을 기억"하는 것이 신뢰할 수 없다는 것을 보여주며, 반드시 AGENTS.md에 규칙을 작성해야 합니다.

사、Workflow 수정 전의 결과물이 성공했지만 verify 프로세스가 잘못된 실패로 판단

디버깅 중간에 확인 목적으로 직접 cat workflow.json을 실행하면 다음과 같았습니다:

$ python3 -m json.tool ~/.flocks/plugins/workflows/tdp_vul_triage/workflow.json
JSON 유효
$ python3 -c "import json; print(len(json.load(open('...'))['nodes']))"
10

완전히 사용 가능한 워크플로가 계속해서 하드 디스크에 존재합니다. write 도구는 실제로 특정 호출에서 이미 조용히 성공했지만, Rex가 작성한 verify 스크립트(bash heredoc로 작성되어 절단되었습니다)가 오류를 보고하여 Rex는 계속해서 작업이 실패했다고 생각하고 반복적으로 재시도했습니다.

교훈: 각 오류 보고 시 가장 간단한 방법(cat / file / ls)으로 결과물이 실제로 존재하고 유효한지 확인한 후, 다시 할지 결정해야 합니다. 이 SOP는 이후 유사 문제를 방지하는 데 도움이 되었습니다.

오、컨텍스트 창 구성이 지나치게 보수적

워크플로 설계가 점차 복잡해지자, 대화에 많은 컨텍스트가 누적되었습니다:

복잡한 작업 중 하나가 빈 응답을 직접 반환했습니다:

오류: 모델 'qwen3.6-plus'이 3번 재시도 후에도 빈 응답을 반환했습니다.

문제를 조사한 결과, WebUI 모델 목록에서 qwen3.6-plus의 "컨텍스트 창"이 128K로 구성되어 있었습니다:

하지만 Flocks 내부의 catalog.json에서 이 모델의 실제 context_window은 991K입니다. WebUI 기본값 128K는 모델의 실제 능력보다 훨씬 낮으며, 128K 기준 압축 임계값은 약 54K에서 발생했습니다.

수정: WebUI 모델 목록에서 qwen3.6-plus의 "컨텍스트 창"을 128000에서 991000으로 변경하면 압축 지점이 약 834K로 상승합니다.

이 제안은 Flocks 팀에 전달되었습니다: WebUI에 모델을 추가할 때 기본값은 catalog.json에서 해당 모델의 실제 context_window을 자동으로 가져와야 하며, 보수적인 자리 값이 아니어야 합니다.

육、Workflow의 ask_* 노드의 위험한 기본값

CVE-2026-40887를 점검하기 위해 워크플로를 실행할 때, Rex가 모든 노드를 자동으로 실행하고 사용자 상호작용을 기다리지 않았으며, 마지막에 생성된 보고서는 "영향을 받는 자산을 발견하지 못함"이라고 말했습니다. 실행 로그에서 다음과 같았습니다:

ask_asset_check 출력:
  user_input: "영향을 받는 자산을 발견했습니까: 아니오\nTDP 확인 위치: N/A"
                              ^^
                              사용자가 전혀 답변하지 않았습니다. 이것은 기본값입니다

소스 코드에서:

outputs['user_input'] = inputs.get('user_response', '') or '영향을 받는 자산을 발견했습니까: 아니오\nTDP 확인 위치: N/A'

모든 5개의 ask_* 노드가 이 안티 패턴입니다. 결과: 사용자가 답변하지 않음 → 기본값으로 "아니오" 채움 → 다운스트림 parse 노드가 "문제 없음"으로 해석 → 보고서에 "무 영향" 결론 생성. 이것은 보안 시나리오에서 절대적으로 범해서는 안 될 실수이며, 정보 부족은 문제가 없다는 의미가 아닙니다.

수정: __NO_RESPONSE__를 사용하여 사용자가 답변하지 않은 상태를 명시적으로 표시합니다:

_resp = (inputs.get('user_response', '') or '').strip()
if not _resp:
    outputs['user_input'] = '__NO_RESPONSE__'
    outputs['user_responded'] = False
else:
    outputs['user_input'] = _resp
    outputs['user_responded'] = True

다운스트림 parse 노드는 다음과 같이 수정합니다:

if ui == '__NO_RESPONSE__' or not ui or not ui.strip():
    acr = {
        'has_affected': '__NOT_CONFIRMED__',   # 'no'가 아님
        'host_list': '사용자가 확인하지 않음',
        'tdp_location': '사용자가 확인하지 않음',
        'responded': False,
    }
else:
    # 기존 파싱 로직
    ...

generate_report 노드는 단계 중 responded: False가 발견될 때 문서 시작 부분에 완전성 알림 섹션을 추가합니다:

unconfirmed_steps = [
    name for key, name in step_names.items()
    if ar.get(key, {}).get('responded') is False
]
if unconfirmed_steps:
    add_h1(doc, '⚠ 보고서 완전성 알림')
    add_body(doc, f'이번 점검에서 다음 {len(unconfirmed_steps)}개 단계에서 사용자가 피드백을 제공하지 않았으며, 관련 결론은 참고용입니다:')
    for s in unconfirmed_steps:
        add_body(doc, f'· {s}')

LLM summarize 노드가 완전성 메타 정보를 받은 후 출력은 다음과 같이 합리적이게 됩니다:

위험 등급: 높은 위험
이유: 전체 체인 점검 결과 모두 "미확인/무응답"이며, 취약점 노출 상황, 공격 흔적 및 수정 상황이 완전히 맹목적 상태입니다.
유효한 검증 없이는 잠재적 위협이 존재하는 것으로 간주합니다.

이것이 보안 분석 로직에 부합하는 판단입니다.

부가적으로 말씀드리면: Flocks의 run_workflow 도구는 노드 수준의 "사용자 입력 대기" 일시 중지 상태를 지원하지 않습니다. 이는 모든 기본값을 삭제하더라도 워크플로가 ask_* 노드에 도달해도 실제로 사용자를 기다리지 않음을 의미합니다. 진정한 단계별 상호작용 점검을 구현하려면 Rex가 워크플로.json을 "스크립트"처럼 취급하고 대화에서 노드 순서에 따라 사용자를 직접 안내해야 합니다.

칠、보고서 출력 형식 제약 — markdown에서 docx 공문으로

업무 요구사항은 GB/T 9704-2012에 부합하는 중국 공문 형식 docx 출력입니다. Rex의 "가짜 수정" 행동:

소스 코드의 작성 방법:

rpt.append('# ' + cve + ' 취약점 점검 상황 보고서')
rpt.append('')
rpt.append('(문서 제목: 흑체 2호 글자 중앙 정렬)')   # 규범 설명을 마크다운 문자열에 작성

이것은 규범 설명 문자열을 마크다운에 작성하고 마지막에는 .md 파일입니다.

해결 방법: 전용 chinese-docx-format 스킬을 생성하여 python-docx의 올바른 사용법과 발생 가능한 문제 참조를 캡슐화합니다:

스킬 디렉토리 구조:

chinese-docx-format/
├── SKILL.md                          # 트리거 조건, 강제 규칙
├── references/
│   ├── python_docx_pitfalls.md       # 8가지 일반적인 발생 문제
│   └── gov_format_spec.md            # GB/T 9704-2012 규범
└── templates/
    └── gov_docx_template.py          # 완전히 실행 가능한 템플릿

스킬에서 몇 가지 중요한 python-docx 구현:

# 중국어 글꼴 설정의 유일한 올바른 방식 —— 반드시 OxmlElement + eastAsia 사용
def set_font(run, font_name, size_pt=None, bold=False):
    rPr = run._element.get_or_add_rPr()
    rFonts = rPr.find(qn('w:rFonts'))
    if rFonts is None:
        rFonts = OxmlElement('w:rFonts')
        rPr.append(rFonts)
    rFonts.set(qn('w:eastAsia'), font_name)   # 핵심
    rFonts.set(qn('w:ascii'), font_name)
    rFonts.set(qn('w:hAnsi'), font_name)
    run.font.name = font_name
    if size_pt: run.font.size = Pt(size_pt)
    if bold: run.font.bold = True

# 행간 "고정값 X 포인트"는 반드시 EXACTLY 규칙 사용
para.paragraph_format.line_spacing_rule = WD_LINE_SPACING.EXACTLY
para.paragraph_format.line_spacing = Pt(28)

run.font.name = '방송_GB2312'만 사용하는 것은 충분하지 않으며, 이는 서양어 글꼴만 설정하고 중국어 부분은 기본 송체로 되돌아갑니다. 이것은 python-docx 문서에 명시적으로 언급되지 않았지만 실제 작업에서 반드시 발생하는 문제입니다.

스킬 생성 후 새로운 문제가 발생했습니다 - 사용자가 PDF를 업로드하여 Rex가 대화에서 직접 보고서를 생성하려고 할 때, Rex 워크플로를 따르지 않고 직접 대화에서 마크다운을 생성합니다:

이전 SOP는 워크플로 노드에만 적용되었으며, "대화 시나리오"를 포함하지 않았습니다. LLM은 자유 대화 시나리오에서 다음과 같이 합리화할 경향이 있습니다: "대화 시나리오에서 마크다운 표시가 더 편리합니다". 해결 방법은 AGENTS.md에 전 시나리오에 적용되는 규칙을 추가하는 것입니다:

## 보고서 출력 형식 약정 (강제 / 전 시나리오 적용)

다음 중 하나의 경우가 발생할 때 반드시 docx 형식으로 출력하고, 마크다운 출력을 금지합니다:

- 사용자가 "보고서 생성 / 출력 / 점검 보고서 / 점검 지원"을 요청할 때
- 사용자가 "공문 / 붉은머리 문서 / 공식 문서 / Word"를 언급할 때
- 워크플로의 generate_report* 노드
- 사용자가 문서를 업로드하여 "점검 지원 및 결과 생성"을 요청할 때
- 최종 제공물로 500자 이상의 "완전 문서"를 write할 것 같은 모든 시나리오

적용 범위는 워크플로로 제한되지 않으며, 자유 대화 시나리오에 동일하게 적용됩니다.
LLM은 "대화 시나리오에서 마크다운이 더 편리하게 표시된다"고 생각하며 이 규칙을 위반할 수 있습니다.
마크다운은 대화 내의 임시 초안/간단한 답변/중간 분석에만 사용되며,
최종 제공물로서의 보고서 파일이 될 수 없습니다.

규칙을 추가하고 Flocks를 재시작하고 새 대화를 시작한 후, Rex의 표현이 올바르게 되었습니다 - 작업이 시작되자마자 SKILL.md와 템플릿을 읽습니다:

공문 규범에 부합하는 docx 보고서를 성공적으로 생성했습니다:

팔、위협 정보 소스 호출 문제

query_cve_intel 노드가 "정보 조회 전부 실패, 사용자 수동 입력 모드로 전환"이라고 보고했습니다. 하지만 동일한 도구를 개별적으로 테스트하면 정상적이었습니다:

테스트 파라미터 JSON 형식에서 문제를 겪었습니다(따옴표 누락):

올바른 형식 {"vuln_id": "CVE-2026-33032"}로 호출한 후 성공:

도구는 완전히 정상이며 CVE-2026-33032의 완전한 취약점 세부 정보를 반환했습니다. 하지만 워크플로 내에서 호출하면 실패하므로 문제는 워크플로 자체의 호출 방식에 있습니다.

문제를 조사한 결과: route_input 노드가 CVE 번호를 올바르게 추출하여 다운스트림에 전달하지 않았습니다. 워크플로가 cve 경로를 따를 때는 parse_vul_inputquery_cve_intel이 병렬로 실행되며, query_cve_intel이 받은 cve_id는 빈 문자열이었고 threatbook 도구에 전달되어 자연스럽게 찾을 수 없었습니다.

수정: route_input 노드에서 미리 cve_id를 추출하여 다음 노드에 의존하지 않도록 합니다:

import re
cve_match = re.findall(r'(?:CVE|XVE)[-_](\d{4})[-_](\d{4,})', raw, re.I)
if cve_match:
    m = cve_match[0]
    extracted_cve = 'CVE-' + m[0] + '-' + m[1]
    outputs['input_type'] = 'cve'
    outputs['cve_id'] = extracted_cve   # 미리 추출
    outputs['raw_vul_info'] = raw       # 원본 입력 유지

수정 후 재실행하면 4개 정보 소스 모두 성공:

cve_intel_results: [
  {source: threatbook_mcp_vuln_query, result: {완전한 취약점 세부 정보}},
  {source: websearch, result: {6개 권위 있는 소스}},
  ...
]

구、AGENTS.md 수정의 적용 범위

이것은 문서 수준의 작은 문제입니다: AGENTS.md 수정 후, 현재 활성 대화 세션은 여전히 이전 프롬프트를 사용하며 새 대화 세션을 시작해야만 적용됩니다.

원인은 Flocks의 system prompt가 대화 세션 수준 주입이라는 것입니다 - 대화 시작 시 AGENTS.md를 한 번 읽으며, 대화 중간에 서비스를 다시 시작하더라도 활성 대화 세션은 여전히 이전 버전을 사용합니다.

문제를 조사할 때 다음과 같이 Rex에게 규칙을 반복하도록 요청하여 검증할 수 있습니다:

한 문장으로 AGENTS.md의 "중간 파이썬 스크립트 문자열 규범" 섹션에서 나에게 요구하는 핵심 사전 검사 동작은 무엇입니까?

만약 "ast.parse를 사용하여 사전 검사 동작을 수행하라"고 답하면 AGENTS.md가 이미 대화 세션에 로드되었음을 의미합니다. 답하지 못하거나 무작위로 답하면 새 대화 세션을 시작해야 합니다.

Flocks 문서에 이 적용 범위를 명시적으로 설명하여 사용자가 수정 후 세션을 다시 시작하지 않고 반복적으로 "SOP가 왜 적용되지 않는가"라는 혼란을 겪지 않도록 권장합니다.

최종 워크플로

21 노드 / 21 엣지 / 2개 branch / 1개 유효한 join

route_input (CVE 번호 추출)
  → branch_route (입력 유형별 분기)
    → parse_vul_input + query_cve_intel (병렬 정보 조회)
      → build_dynamic_guidance (동적 점검 지시 생성)
        → 5개 ask_* + parse_* (사용자 상호작용)
          → collect_results (요약 + 완전성 메타 정보)
            → summarize_analysis (LLM 요약)
              → ask_report_cve → branch_report_cve
                → generate_report_cve (docx 생성)

실행 결과 비교:

구분 수정 전 수정 후
출력 형식 마크다운 문자열 + .md 접미사 실제 docx
파일명 vul_triage__date.docx(CVE 누락) vul_triage_CVE-XXX_date.docx
데이터 진실성 사용자가 답변하지 않음 → 기본값 "아니오" __NOT_CONFIRMED__ 표시
위험 판정 중위험 (기본값에 속음) 고위험 (정보 부족 시 최악의 경우 처리)
정보 소스 4개 모두 실패 4개 모두 성공
join 설계 branch 후 join: true로 인한 정체 join 필드 삭제

AGENTS.md에 누적된 SOP

각각은 구체적인 발생 사례를 기반으로 합니다:

## 파일 출력 약정
## 기능 격 해결 프로토콜
## 스�일 발견 프로토콜
## 워크플로 JSON 작성 절차
## 기존 워크플로 수정 원칙: 증분 편집
## branch + join 설계 규칙
## 보고서 출력 형식 약정 (전 시나리오 적용)
## 중간 파이썬 스크립트 문자열 규범
## 모델 빈 응답 처리

총 길이 약 350줄. AGENTS.md는 Flocks의 비교적 성숙한 설계입니다 - 이것은 대화 세션 수준 주입의 강력한 제약 규칙이며, 단순한 프롬프트 엔지니어링보다 더 안정적이며 소스 코드 수정보다 가볍습니다. 각 실제 발생 문제는 새 SOP로 이곳에 추가할 수 있으며, 사용자 수준의 엔지니어링 규율이 점점 두꺼워집니다.

워크플로 정적 검사 스크립트

워크플로를 수정한 후 실행하면 5초 안에 join 관함수 함정이 있는지 알 수 있습니다:

#!/usr/bin/env python3
# check_workflow.py
import json, sys, os
from collections import defaultdict

path = sys.argv[1] if len(sys.argv) > 1 else \
    os.path.expanduser('~/.flocks/plugins/workflows/tdp_vul_triage/workflow.json')

wf = json.load(open(path))
upstream = defaultdict(list)
for e in wf['edges']:
    upstream[e['to']].append(e['from'])
branches = {n['id'] for n in wf['nodes'] if n['type'] == 'branch'}

def has_branch_in_upstream(node, visited=None):
    if visited is None: visited = set()
    if node in visited: return False
    visited.add(node)
    for up in upstream[node]:
        if up in branches: return True
        if has_branch_in_upstream(up, visited): return True
    return False

errors = []
for n in wf['nodes']:
    j = n.get('join', None)
    if j is not None and not isinstance(j, bool):
        errors.append(f"{n['id']}: join={j!r} 불법, Flocks는 true/false만 허용")
    elif j is True and has_branch_in_upstream(n['id']):
        errors.append(f"{n['id']}: join=true이지만 경로에 branch가 있어 런타임에 정체됨")

if errors:
    print('\n'.join('❌ ' + e for e in errors))
    sys.exit(1)
print('✅ 정적 검사 통과')

이러한 검사는 Flocks 공식 CLI에서 제공되어야 합니다(예: flocks workflow validate <id>), 현재는 없습니다.

Flocks 사용 피드백

정리 과정에서 발생한 플랫폼 계층 문제:

심각한 문제:

  1. Tool not found: invalid 오류 메시지는 심각한 오해를 불러일으킵니다. 실제로는 파라미터 구문 분석 실패이지만 도구가 존재하지 않는다고 생각하게 만듭니다. Tool argument parse failed: <실제 원인>로 변경하고 content 길이 상한선을 문서에 설명하는 것이 좋습니다.
  2. bash 도구의 command 파라미터는 약 6KB에서 무단으로 절단되며 경고도 없고, bash는 불완전한 명령어를 직접 실행하여 다양한 SyntaxError를 유발합니다. 이러한 무단 실패는 직접 오류를 보고하는 것보다 훨씬 어렵습니다. 절단이 감지될 때 명시적으로 오류를 발생시키고 길이 상한선을 문서에 설명하는 것이 좋습니다.
  3. 워크플로의 join 필드는 schema 수준에서 bool만 허용하지만, 사용자는 종종 "임의 업스트림" 의미가 필요합니다. 현재 사용자가 "필드 삭제"를 표현해야만 any 의미를 나타낼 수 있으며 직관적이지 않고 문서에 설명되지 않았습니다. join 필드를 열거 값(any / all / false / true)으로 변경하거나, 워크플로 로드 단계에서 branch + join: true 조합에 대한 정적 검사를 수행하고 오류를 발생시켜 안내하는 것이 좋습니다.
  4. WebUI 모델 목록의 "컨텍스트 창" 기본값이 지나치게 보수적입니다. Qwen3.6-Plus의 catalog 표시는 991K이지만 WebUI 기본값은 128K로 설정되어 있어 "명백히 대형 모델을 사용하는데 자주 컨텍스트 압축이 발생한다"는 느낌을 줍니다. catalog에서 실제 context_window을 자동으로 가져와 기본값으로 사용하는 것이 좋습니다.
  5. 워크플로의 ask_* 노드는 사용자 입력 대기 일시 중지 상태를 지원하지 않습니다. run_workflow 도구는 한 번에 실행되며 모든 ask_* 노드의 "사용자 응답 누락"은 기본값으로 채워져 완전히 기본값으로 위조된 보고서가 생성됩니다. 노드 수준의 waiting 상태를 제공하거나 문서에서 이 제한 사항을 명시적으로 설명하는 것이 좋습니다.

개선이 필요한 사항:

  1. 워크플로 증분 편집 도구가 부족합니다. agent의 기본 동작은 "전체 파일 재작성"이지만 write/bash의 파라미터 제한으로 인해 재작성은 거의 실패합니다. 노드 수준의 추가/삭제/수정을 지원하는 workflow_edit 유형 도구를 제공하는 것이 좋습니다.
  2. 공식 워크플로 정적 검사 CLI를 제공합니다.
  3. AGENTS.md 수정은 새 대화 세션에서만 적용되므로 문서에 명시적으로 설명해야 합니다.
  4. tdp-use 스킬의 references 파일 이름 대소문자가 일치하지 않습니다(TDP-menu.md 대문자 vs event-detail.md 소문자), 전체 소문자로 통일하는 것이 좋습니다.

이번 배포에 대한 몇 가지 관찰

전체 과정에 소요된 시간은 예상을 크게 초과했지만, Flocks의 몇 가지 핵심 설계가 합리적임을 증명했습니다:

  • AGENTS.md는 사용자 정의 가능한 agent 지시 계층으로서 유연성이 좋습니다. SOP는 실제로 agent 동작을 변경할 수 있으며, 이러한 "사용자 수준 규칙" 메커니즘은 단순한 프롬프트 엔지니어링보다 안정적이며 소스 코드 수정보다 가볍습니다.
  • workflow.json은 DAG 설명으로서 branch + 여러 합류 노드의 의미 자체는 건강합니다.
  • Rex의 self-enhance / capability gap protocol는 상대적으로 진보된 agent 자율 설계입니다 - agent는 능력 부족을 인식하고 하위 agent를 생성하여 도구를 작성할 수 있으며, 이러한 메커니즘은 "이 일을 할 도구가 없어"라는 많은 정체를 감소시킵니다.
  • WebUI의 시각화 및 테스트 실행 경험은 원활합니다.

주요 문제점은 도구 파라미터 제한, 오류 메시지 안내, schema 제약과 같은 DX 계층에 집중되어 있으며, 피드백 후에는 상대적으로 쉽게 수정할 수 있을 것입니다. 다른 자체 배포를 고려하는 동료들에게 참고가 되기를 바랍니다.

태그: AgentSecOps Flocks LLM Workflow Security

7월 4일 22:52에 게시됨