
[ 글의 목적: LLM의 오케스트레이션과 하네스, opencode 와 OMO 의 탄생 배경과 how to use 정리, 이미지 빼고 AI가 안썼어요.. 사람이 썼어요..🥹 ]
LLM 평가 축은 빠르게 변하고 있습니다. 이제 “모델이 얼마나 똑똑한가”만으로는 체감 품질을 설명하기 어렵습니다!! 실제 현업에서의 생산성은 긴 작업을 얼마나 안정적으로 이어갈 수 있는지, 그리고 도구·컨텍스트·검증 루프를 얼마나 잘 운영하는지에서 갈립니다.
LLM 의 스케일링 법칙(Scaling Laws)은 이제 한계라는 의견이 많습니다. (참조 링크). 더욱이 SLM 을 특정 작업에 맞춰 최적화하고, 고품질 데이터로 재학습시키고, 나아가 MoE 구조로도 사용합니다.
특히 신규 LLM 모델은 진짜 "체감할 수 있는 차이" 에 있어서 "구체적으로, 그리고 정량적으로 우리의 작업이 얼마나 나아졌는가" 를 설명하기 매우 어려워졌습니다.
모델 경쟁이 끝난 것은 아닙니다. 하지만 차별화의 중심축은 이미 위 레이어로 올라가고 있습니다. 특히 코딩, 리서치, 마이그레이션, 대규모 리팩토링처럼 길고 복잡한 작업에서는 “한 번 잘 답하는가”보다 “끝까지 안정적으로 완주하는가”가 훨씬 중요합니다. 그리고 그 완주 능력을 만들어내는 것이 바로 에이전트 하네스(Agent Harness)입니다.

OpenCode는 스스로를 오픈소스 AI 코딩 에이전트로 소개하며, 터미널 기반 인터페이스, 데스크톱 앱, IDE 확장 형태로 사용할 수 있습니다. LSP 지원, 멀티 세션, 세션 공유 링크, 다양한 모델 프로바이더 연결을 핵심 특성으로 내세웁니다. 즉 OpenCode는 단순한 “채팅형 코딩 도구”라기보다, 에이전트를 실행하는 런타임에 더 가깝습니다.
즉, OpenCode 자체가 이미 “에이전트 실행기 + 도구 런타임 + 세션 관리자” 성격을 갖고 있고, 그 위에 플러그인을 얹어 하네스 역량을 키우는 구조입니다.
아주 아주 기본적인 개념은 "다양한 LLM 들을 하나의 tool 에서 모아서 사용" 이라는 점에서 크게 다르지 않습니다. 세션 단위로 작업 컨텍스트를 유지하며, 사용자는 TUI에서 입력/전환/실행을 수행합니다. (실행 시 TUI와 HTTP 서버가 함께 뜨는 client/server architecture)

최근에는 mode 보다 agent 구성이 중심이지만, 사용 경험상 여전히 많은 분들이 Build 와 Plan 을 “모드”처럼 이해하고 있습니다. (물론 저도요 ㅎ)
내장 primary agent는 Build 와 Plan 이고, subagent로는 General 과 Explore 가 제공됩니다. (근데 다들 각자 플러그인을 많이 사용하다보니 순정을 보기 힘들어진 기분)
Build 는 일반 개발 작업용으로 모든 도구 접근이 열려 있고, 실제 편집, 패치, 명령 실행, 검증에 적합합니다.Plan 은 파일 수정과 bash 실행을 제한하거나 승인 기반으로 다뤄 분석과 설계 중심으로 쓰이도록 설계되어 있고, 분석, 설계, 변경안 검토, 위험 식별에 적합합니다. (기본적으로 파일 수정과 bash 실행이ask 로 제한됨)General 은 범용적이게 사용하고,Explore 는 읽기 & 탐색 중심!compaction, title, summary 같은 숨겨진 시스템 에이전트가 자동 실행된다고 합니다. 사실 이런 접근은 이제 아주 일반화가 된 것 같습니다. 저 역시 바이브 코딩과 LLM에 대한 대규모 서베이, Augmented Coding 글과 같이 "plan" 의 중요성을 매우 체감하고 있네요.
[ 권한 제어와 도구들의 디테일 ]
allow, ask, deny로 제어되고read, edit, bash, task, lsp, webfetch, websearch, codesearch 같은 항목별로 통제한다고 합니다. grep, glob, list 는 내부적으로 ripgrep 을 사용하며, .gitignore 를 따른다고 하며 (디테일), 사실 LLM 기반으로 마치 Re-ACT agent, tool calling 처럼, 도구 호출 중심 실행 프레임워크로 만들어졌다고 보는게 맞는 것 같네요.[ LSP(Language Server Protocol) ]

플러그인은 JavaScript/TypeScript "모듈 형태로 훅"을 내보내며, 로컬 플러그인 디렉터리 또는 npm 패키지 방식으로 로드할 수 있습니다.
npm 플러그인은 시작 시 Bun으로 자동 설치되며, 캐시는 ~/.cache/opencode/node_modules/ 에 default로 저장됩니다.
로드 순서는 [ 전역 config → 프로젝트 config → 전역 dir → 프로젝트 dir ] 입니다. 에이전트 하네스 쪽은 보통 설정 충돌, 훅 순서, 컨텍스트 주입 순서 때문에 디버깅이 어려운데, OpenCode는 적어도 플러그인이 어디서, 어떤 순서로 붙는지를 문서화해 둔 편입니다. 그래서 플러그인 생태계가 잘 만들어질 수 있었던 것 같네요.
(작성일 기준이라 공식 홈페이지 한 번 참고하시는게 좋습니다. - https://opencode.ai/ko), 최근에는 데스크톱 앱이 나온 것 같네요!
curl -fsSL https://opencode.ai/install | bash
역시 인기있는 tool 들은 설치와 세팅이 아주 간단합니다. 설치 후 opencode 로 실행이 끝입니다. 이후 /connect 커맨드 활용해서 "프로바이더 (상용 LLM 포함 외부 LLM auth 세팅)" 세팅까지 이어가면 바로 사용 가능합니다!


Oh My OpenCode는 공식 사이트에서 스스로를 “OpenCode 위에 올라가는 specialized orchestration layer” 라고 설명합니다. OMO는 OpenCode를 대체하는 별도 제품이 아니라, OpenCode 위에 에이전트, 훅, MCP, LSP, 설정값을 묶어 더 강한 운영 구조를 제공하는 플러그인 입니다!
그냥 “코드를 잘 써주는 도구”가 아니라
를 기반으로 "잘 굴러가게 만드는 하네스" 를 지향합니다. "AI 팀" 에 비유 하며 다수의 전문 에이전트(역할 분업), 스킬(워크플로 템플릿), 커맨드(/refactor 등), 훅(키워드 감지/복구/알림/컨텍스트 주입)을 묶어서 제공한다고 설명합니다. (플러그인 공식 깃헙 레포, 관련 긱뉴스, 제작자 유튜브 인터뷰(팟캐스트))

OMO는 기본적으로 Planner-Sisyphus, Librarian, Explore, Oracle 같은 전문 에이전트를 제공합니다. Sisyphus 를 기본 오케스트레이터로 설명하고, Prometheus, Metis 같은 계획 보조 에이전트, 그리고 frontend-ui-ux-engineer, document-writer, multimodal-looker 같은 역할 특화 에이전트가 있습니다.
@ 를 통해서 에이전트를 타겟할 수 도 있습니다!

이게 지금의 OMO를 만들어준, 하이라이팅될 수 있던 feature들이 아닐까 하네요, OMO는 "키워드 기반 감지" 로 "하네스" 가 작동이 됩니다. ultrawork 또는 ulw 는 최대 성능 모드, search 또는 find 는 병렬 탐색 모드, analyze 또는 investigate 는 심층 분석 모드로 안내가 됩니다. 또 think deeply, ultrathink 같은 표현은 think mode 훅이 감지해 추론 설정을 조정한다고 합니다.
사용자가 “이번 작업의 성격”만 잘 말해도 하네스가 행동 방식을 바꿔주기 때문입니다. 즉 프롬프트가 단순 지시문이 아니라, 오케스트레이션 정책을 바꾸는 신호가 됩니다.
ultrawork, 줄여서 ulw는 OMO README에서 사실상 “마법의 단어”처럼 소개됩니다. 공식 README 표현을 정리하면, 병렬 에이전트 실행, 백그라운드 작업, 적극적 탐색, 완료까지 밀어붙이는 성격을 가진 최대 성능 모드입니다. 대규모 리팩토링, 복잡한 마이그레이션, 여러 파일과 여러 축의 검증이 동시에 필요한 작업에 잘 맞습니다.
기본 오케스트레이터가 작업을 분해하고, 전문 에이전트를 공격적으로 병렬 실행하는 성격으로 설계돼 있다고 설명합니다. 즉 자체적으로 "각 업무 전문가에게 일을 할당하고, 평가하고, 리팩토링하고 등" 이 모두 묶여있습니다. (다음 섹션에서 저는 어떻게 ulw 를 사용하는지 정리해 뒀습니다!)
이 모드는 빠른 코드베이스 탐색이 핵심입니다. OpenCode의 내장 Explore 가 원래 읽기 전용 탐색 성격을 갖고 있는데, OMO는 이런 탐색 성격을 더 공격적으로 활용합니다. 레거시 프로젝트 진입점 찾기, 설정 파일 찾기, 실제 호출 경로 파악, 특정 동작이 어디서 시작되는지 확인할 때 특히 유용합니다.
이 모드는 구현보다 해석과 판단에 가깝습니다. 장애 원인 분석, 설계 리뷰, 트레이드오프 비교, “왜 이런 구조가 되었는가”를 증거 기반으로 정리할 때 잘 맞습니다. 공식 사이트의 Oracle 소개와 README 설명을 합치면, 코드 설명과 문제 진단, 아키텍처 판단을 보조하는 방향으로 이해할 수 있습니다.
문서는 oracle을 “아키텍처 결정/코드 리뷰/디버깅(읽기 전용)” 상담역으로 설명합니다.
Think mode는 구현 이전 사고 비용을 늘리는 장치입니다. “바로 고치지 말고 먼저 깊게 생각해라”라는 의도를 하네스 차원에서 반영합니다. 문제 정의가 불분명하거나, 정책과 SDK 제한을 함께 검토해야 하거나, 근거를 모아 판단해야 할 때 특히 유효합니다.
think-mode 훅이 관련 키워드를 감지해 모델 설정(extended thinking 등)을 조정한다고 명시합니다. (사견으로는 생각 자체에 회귀를 할 때가 있어서 적절한 결론에 대한 신호 체계를 만드는게 좋습니다!)
물론 OpenCode 설치가 무조건 선행되어야 합니다. 하지만, 역시 간단합니다. (bun 런타임이 필요합니다.)
bunx oh-my-opencode install
그러면 세팅 가이드가 자동으로 안내를 해줍니다!




OMO의 ulw 는 진짜 한 줄만 줘도 진정한 의미의 "바이브코딩" 을 합니다. "딸각" 이 가능하죠. 근데 제가 여전히 구시대적인 사람인지 몰라도 저는 이게 너무 와닿지 않습니다. "통제 가능성" 과 "일관성", "규칙" 이 저에게는 너무 중요해서..
stack 부터 정합니다.AGENTS.md (CLAUDE.md 등 포함) 부터 출발합니다./init 으로 직접 이 마크다운을 만드는 경우가 많지만, 저는 여전히, Augmented Coding 에서 차용한 TDD와 Tidy code를 아주 적극적으로 사용합니다.AGENTS.md 에는 "논리적인 방법론" 들을 정리합니다. 기본적인 역할, TDD, Tidy First, Quality 등에 대해서요.SYSTEM_DESIGN.md 를 만듭니다.python 으로 작업할땐 꼭 아래 시스템 디자인으로 출발합니다. 포인트는 Do not over-apply design patterns# SYSTEM_DESIGN
This document defines the core system design rules for this project.
---
## 1. Python Version & Typing
- We use **Python 3.13 or higher**.
- Do **not** use the `typing` module for type hints.
- Always use **built-in types** for annotations (e.g., `int`, `str`, `list`, `dict`, etc.).
---
## 2. Code Style
- Follow the **Google Python Style Guide**:
- <https://google.github.io/styleguide/pyguide.html>
- Follow **PEP 8** (Python’s official style guide):
- <https://peps.python.org/pep-0008/>
If there is any conflict between local conventions and these guides, prefer clarity and consistency within this project.
---
## 3. Object-Oriented Design
We favor **object-oriented programming (OOP)** and its core principles:
- **Encapsulation** – Group related data and behavior inside classes and hide internal details.
- **Abstraction** – Expose clear interfaces and hide unnecessary implementation details.
- **Inheritance** – Reuse behavior via well-designed base classes and subclasses when appropriate.
- **Polymorphism** – Design interfaces so that different implementations can be used interchangeably.
OOP should improve readability and maintainability, not add unnecessary complexity.
---
## 4. Architectural Pattern
- We **aim for a layered architecture pattern** (e.g., presentation, application/service, domain, infrastructure).
- Each layer should have a clear responsibility and minimal knowledge of other layers.
At the same time:
- Do **not** over-apply design patterns or split the codebase into too many tiny files.
- Avoid “architecture for architecture’s sake.”
- Aim for:
- **Reasonable maintainability**
- **Reasonable separation of concerns**
- **Always pragmatic, balanced design**
In short, we prefer a **practical, moderately layered architecture** that is easy to understand, extend, and maintain, rather than a theoretically "perfect" but over-engineered structure.
mypy 보다는 pyright 가 좀 더 유연한 측면에서 맞는 것 같네요. pre-commit, ruff(eslint & prettier), test(pytest, jest) 세팅을 바로 합니다.uv + ruff 으로 아래 기본 세팅은 하고 갑니다. 스크롤이 너무 길어져서 뺄까 했는데, 혹시나 다른 분들을 위한 설정 값 공유!(아래 pre-commit)
ci:
autoupdate_schedule: monthly
default_language_version:
python: python3.13
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: check-yaml
- id: check-toml
- id: check-added-large-files
- id: check-merge-conflict
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.0
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- id: ruff-format
- repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.10.2
hooks:
- id: uv-export
args:
- --frozen
- --no-dev
- --no-hashes
- --output-file=requirements.txt
- --quiet
(아래 toml 에서 기본 설정들)
# ================================================================
# Ruff (Linter & Formatter) Settings
# ================================================================
[tool.ruff]
# 수정에서 제외할 파일 및 디렉토리 목록
exclude = [
".bzr",
".direnv",
".eggs",
".git",
".hg",
".mypy_cache",
".nox",
".pants.d",
".pytype",
".ruff_cache",
".svn",
".tox",
".venv",
"__pypackages__",
"_build",
"buck-out",
"build",
"dist",
"node_modules",
"venv",
"*/migrations/*.py",
]
# 한 줄의 최대 글자 수
line-length = 100
# --- Linter (코드 분석기) 설정 ---
[tool.ruff.lint]
# 활성화할 규칙 선택:
# E, W: pycodestyle (에러, 경고)
# F: Pyflakes (논리적 오류)
# I: isort (import 정렬)
select = ["E", "F", "W", "I"]
ignore = []
# 모든 수정 가능한 규칙을 자동으로 고치도록 설정
fixable = ["ALL"]
unfixable = []
# --- Formatter (코드 포맷터) 설정 ---
[tool.ruff.format]
# Black과 유사한 포맷팅 스타일을 따릅니다.
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"
# --- 플러그인별 상세 설정 ---
[tool.ruff.lint.isort]
# 프로젝트에서 사용하는 서드파티 라이브러리 목록
# known-third-party = ["django", "graphene_django"]
# --- 파일/디렉토리별 규칙 무시 설정 ---
[tool.ruff.lint.per-file-ignores]
# settings 파일: 와일드카드 import 허용
# "config/settings/*" = ["F403", "F405"]
# __init__.py 파일: 하위 모듈 노출을 위한 미사용/와일드카드 import 허용
"**/__init__.py" = ["F401", "F403"]
# 테스트 파일: 가독성을 위해 긴 줄 허용
"**/test_*.py" = ["E501"]

github cli 인 gh 를 기가막히게 잘 쓰더라구요. 그래서 더욱이 CI 부터 세팅하려고 합니다. 위는 python, uv 기반 CI 파이프라인이고, 처음부터 멀티 버전 (매트릭스) 대상으로 하지는 않습니다. 
plan.md 부터 작성합니다. 이게 AGENTS.md 에서 명시한 것들과 일맥상통하기도 하고, "통제 가능성" 이 여전히 중요하기도 하구요. 그리고 여전히 저는 무조건 테스트 코드 부터 작성합니다.

plans 디렉토리에 따로 모아둬요!
.sisyphus 경로에 자동으로 저장이 되긴 합니다.
/start-work 라는 사전 명령어를 사용해서 시작합니다. 그러면 .sisyphus 경로에 자동 저장된 plan 찾아서 바로 작업을 이어가고, agent 에게 일을 할당해주기 시작합니다!
AGENTS.md 에 따르면 go 라는 시그널만 주는데, 이는 좀 때에 따라 다르게 하긴 합니다. ulw 가 필요하다 싶으면 Sisyphus 를 사용합니다!

plan.md 기반으로 모든 사항이 적용되었는지 A to Z 를 검토해야 해.
아래 사항에 따라 검토하되, 체크 박스도 모두 제대로 처리 해.
1. AGENTS.md 와 SYSTEM_DESIGN.md 를 1순위로 따르고 있는지 체크.
2. 변경에 따른 하위호환성과 영향 범위를 절대 잊지말고 더블 체크.
3. 관련된 테스트 코드 역시 업데이트 되어야 해.
4. 관련된 테스트가 과하거나, 중복되거나, 이미 자명한데 쓸데없는 테스트를 하거나 하지 않는지 체크
5. 2025년, 2026년 외부 공식 자료와 외부 best example 을 참고해서 개선해줘. 최대한 비판적으로 수용하고 지금 코드를 업데이트 해야 해.
이를 위해 다양한 모델과 서브에이전트를 적극적으로 활용해.

ui-ux-pro-max 
skill 과 하네스를 섞어서 쓰기도 합니다. 이땐 작업 범위가 좁을수록 output 이 좋았습니다. 진행할 수 록 layer 는 많아지고 무조건 프로젝트는 복잡성이 올라갑니다. 그래서 무조건 이 AI를 위한 마크다운을 초기설정 그대로 두지 않습니다!
무조건 프로젝트 현 상태에 따라 맞춰 업데이트를 합니다! 일례로, 동시성에 대한 경고, web이 아닌 OS응용 프로그램, GUI를 위한 룰, 또는 FE 작업할땐 "DESIGN_SYSTEM.md" 도 만드는데, 이 디자인 룰 역시도요.
AGENTS.md 와 같이 기본적으로 에이전트가 물고가는 마크다운 파일은 더욱더요!Research Agent
↓
Planner Agent
↓
Implementation Agent
↓
Reviewer Agent
↓
Documentation Agent

ctrl + c 로 취소하거나 /new 로 바로 새로운 세션을 시작할 필요가 없습니다!
/handoff 를 쓰면 됩니다! /handoff 는 현재 에이전트나 세션의 작업 상태(context)를 다른 에이전트 또는 다음 단계의 작업으로 넘기는 작업 전달 메커니즘입니다. 


정리해 보면 opencode + OMO 세팅에서 아래 4~5가지 흐름으로만 사용하는 것 같습니다.
프로젝트 세팅부터 AI 마크다운들 포함해서 제대로.
불확실한 요구사항/큰 작업
Prometheus (Plan Builder) 로 planAtlas (Plan Executor) 또는 Sisyphus (Ultraworker) 를 통해 ulw 를 붙여 병렬 실행을 유도(하네스 최대 가동). 레거시 코드 파악이 먼저인 작업
find 또는 search 를 포함해 탐색 모드로 시작@explore 에게 “진입점/핵심 모듈/핫스팟 파일”을 먼저 뽑게 하고(쓰기 제한이 있어 안전), 이후 Build로.디버깅/근본원인 분석
investigate를 넣어 분석 모드로 전환@oracle 을 “읽기 전용”으로 붙여 객관화볼륨이 크지는 않지만 특정 부분 (또는 역할) 만 업그레이드 할 경우
특히 3번 4번은 오픈소스 코드들 또는 이미 볼륨이 있고 커진 프로젝트에서 특정 부분만 집중할때 꽤나 좋았었습니다.
요즘처럼 AI 관련 stack들이 생명주기가 반년도 안되는 시대에 이런 접근이나 방법들이 또 언젠가 레거시 처럼 여겨질지도 모르겠네요..!
아! 가끔 자기전에, 외출전에 랄프(Ralph Loop)를 가동하긴 합니다. 근데 개인적으로 랄프보단 ulw 를 프롬프트로 자동회귀하게 세팅하는게 체감 성능이 좋더라구요..
plan 을 가득 가득 만들어두고 한 호흡으로 진행하라는, 즉 무조건 끝날때까지 진행하는 프롬프트와 ulw 돌리시면 토큰 사용 다 할때까지 돌아가는 마법을 보실 수 도 있습니다..
opencode stats 를 한 번 입력해보세요! - https://opencode.ai/docs/cli/


Cache Read 에 24억 7,120만 토큰 정도 사용했네요! 적어주신 SYSTEM_DESIGN.md에서 ##1의 "Always use built-in types for annotations (e.g., int, str, list, dict, etc.)" 부분이 특히 공감되네요 ㅎㅎ
지금까지 built-in types를 표준으로 사용하지 않던 시기가 더 길어서, AI가 해당 스타일의 코드를 상대적으로 더 많이 학습했기 때문에 그런 현상이 나타나는 것 같기도 합니다. 🤔
prompt와 설정 공유해주셔서 감사합니다!
review 나 diff check 는 어디까지 하시는지 궁금하네요!