HCL 구성
HCL 구성 (HCL Configuration)
YAML 대신 HCL로 Docker Agent 구성을 작성해요. 같은 Docker Agent 스키마와 검증 규칙에 매핑돼요.
출처: 문서
본문
docker-agent 는 .yaml 또는 .yml 파일을 지원하는 어디서든 .hcl 구성 파일을 지원해요. HCL은 라벨 블록, 더 적은 구두점, 긴 프롬프트용 heredoc을 선호한다면 유용해요.
Tip 같은 구성 모델, 다른 구문 (Same config model, different syntax) YAML과 HCL은 같은 Docker Agent 구성 모델의 두 구문일 뿐이에요. Docker Agent는 HCL을 내부적으로 동등한 YAML 구조로 변환한 뒤 정상 스키마 검증과 로딩 파이프라인을 실행해요.
최소 예제 (Minimal Example)
#!/usr/bin/env docker agent run
agent "root" {
model = "openai/gpt-5"
description = "A helpful assistant"
instruction = <<-EOT
You are a helpful assistant.
EOT
toolset "think" {}
}
YAML 구성처럼 정확히 실행해요:
$ docker agent run agent.hcl
$ docker agent run --exec agent.hcl "Summarize this repository"
$ docker agent serve api ./agents/ # directories may mix .yaml, .yml, and .hcl files
Tip 참고 (See also) HCL은 구문만 바꾸지 필드의 의미는 바꾸지 않아요. 각 필드가 무엇을 하는지 보려면 Agent Config, Model Config, Tool Config 참고.
YAML vs HCL
이 두 구성은 동등해요:
models:
claude:
provider: anthropic
model: claude-sonnet-4-5
agents:
root:
model: claude
description: Coding assistant
instruction: You help with software development.
toolsets:
- type: filesystem
- type: shell
model "claude" {
provider = "anthropic"
model = "claude-sonnet-4-5"
}
agent "root" {
model = "claude"
description = "Coding assistant"
instruction = "You help with software development."
toolset "filesystem" {}
toolset "shell" {}
}
핵심 규칙 (Core Conventions)
HCL은 몇 가지 간단한 매핑 규칙을 따릅니다:
| HCL syntax | YAML shape |
|---|---|
agent "root" { ... } |
agents.root |
model "claude" { ... } |
models.claude |
provider "team" { ... } |
providers.team |
mcp "github" { ... } |
mcps.github |
rag "docs" { ... } |
rag.docs |
agent 안의 command "fix" { ... } |
commands.fix |
toolset "shell" {} |
type: shell 이 있는 toolsets의 목록 항목 |
metadata { ... }, permissions { ... } |
같은 최상위 이름을 가진 singleton 블록 |
최상위 키가 매핑된 것은 라벨 블록이 됨 (Top-level keyed maps become labeled blocks)
YAML에서 여러 섹션은 이름으로 키가 매겨진 맵이에요. HCL에서는 그것들이 라벨 블록이 돼요:
model "claude" {
provider = "anthropic"
model = "claude-sonnet-4-5"
}
agent "root" {
model = "claude"
description = "Primary assistant"
instruction = "You are helpful."
}
지원되는 최상위 라벨 블록:
agentmodelprovidermcprag
지원되는 최상위 singleton 블록:
metadatapermissions
Toolset은 블록 라벨을 type으로 사용 (Toolsets use the block label as type)
type: ... 이 있는 목록 항목을 쓰는 대신, HCL은 라벨이 도구 유형이 되는 toolset 블록을 사용해요:
agent "root" {
model = "openai/gpt-5"
description = "Dev assistant"
instruction = "You can inspect and modify code."
toolset "filesystem" {}
toolset "mcp" {
ref = "docker:github-official"
}
}
명령도 라벨 블록 사용 (Commands use labeled blocks too)
에이전트 명령은 각 명령이 자체 블록을 갖기 때문에 HCL로 작성하기에 종종 더 좋아요:
agent "root" {
model = "openai/gpt-5"
description = "Build helper"
instruction = "You help with builds."
command "fix-lint" {
description = "Fix lint issues"
instruction = "Run the linter, then fix any problems."
}
}
문자열과 Heredoc (Strings and Heredocs)
짧은 값에는 따옴표가 붙은 문자열을, 긴 프롬프트, 환영 메시지, 임베디드 JSON에는 heredoc을 사용해요.
agent "root" {
model = "openai/gpt-5"
description = "Friendly assistant"
instruction = <<-EOT
You are a helpful assistant.
Keep answers concise and practical.
EOT
}
리터럴 ${...} 이스케이프 (Escaping literal ${...})
HCL은 문자열과 heredoc 안의 ${...} 를 템플릿 보간으로 취급해요. 프롬프트에 리터럴 텍스트 ${...} 가 필요하면 $${...} 로 이스케이프해요.
이것은 Docker Agent 템플릿 스니펫을 의도적으로 보여주는 명령 프롬프트에 중요해요:
command "fix-lint" {
instruction = <<-EOT
Run the linter and inspect the result:
$${shell({cmd: "task lint"})}
EOT
}
모델은 리터럴 ${shell({cmd: "task lint"})} 텍스트를 받아요.
file()로 파일 로드 (Loading Files with file())
file() 함수는 UTF-8 텍스트 파일을 읽고 내용을 문자열로 반환해요. 상대 경로는 HCL 구성 파일의 디렉터리에서 해석되고, 읽기는 그 디렉터리로 제한돼요.
긴 프롬프트를 구성 밖에 두는 데 도움이 돼요:
agent "root" {
model = "openai/gpt-5"
description = "Coding assistant"
instruction = file("prompts/coding.md")
}
단일 인자로 파일 내용은 작성된 그대로 반환돼요 — 파일의 어떤 ${...} 도 리터럴로 유지되므로, ${shell({cmd: "..."})} 같은 런타임 스니펫이 그대로 통과해요.
파일을 템플릿으로 렌더링 (Rendering files as templates)
두 번째 인자로 객체를 전달해 파일을 HCL 템플릿으로 렌더링해요. 각 키가 파일 안에서 사용 가능한 변수가 돼요:
agent "reviewer" {
model = "openai/gpt-5"
description = "Go reviewer"
instruction = file("prompts/reviewer.md", {
language = "Go"
strictness = "high"
})
}
agent "py_reviewer" {
model = "openai/gpt-5"
description = "Python reviewer"
instruction = file("prompts/reviewer.md", {
language = "Python"
strictness = "relaxed"
})
}
prompts/reviewer.md 가 다음을 포함한다면:
You review ${language} code with ${strictness} strictness.
템플릿은 %{ for } 와 %{ if } 지시자를 포함한 전체 HCL 템플릿 구문을 지원해요:
Rules:
%{ for rule in rules ~}
- ${rule}
%{ endfor ~}
두 가지를 명심해야 해요:
- 객체에 없는 변수를 참조하면 에러예요.
- 템플릿 안에서는 함수를 사용할 수 없어서, 템플릿이
file()을 다시 호출할 수 없어요. 파일이 템플릿으로 렌더링되는 동안 리터럴${...}를 필요로 하면 파일 안에서$${...}로 이스케이프하세요.
반복 블록이 리스트가 됨 (Repeated Blocks Become Lists)
일부 YAML 섹션은 리스트예요. HCL에서는 반복 블록으로 작성돼요.
예를 들어 모델 라우팅 규칙은 반복 routing { ... } 블록이 돼요:
model "smart_router" {
provider = "openai"
model = "gpt-5"
routing {
model = "anthropic/claude-sonnet-4-5"
examples = [
"Write a detailed technical document",
"Review this code for security issues",
]
}
routing {
model = "openai/gpt-5"
examples = [
"Generate some creative ideas",
"Help me brainstorm",
]
}
}
같은 아이디어가 RAG 전략 블록, 훅 이벤트 항목 같은 다른 리스트 형태 섹션에도 적용돼요.
Terraform과의 중요한 차이점 (Important Differences from Terraform)
Docker Agent는 HCL을 구성 구문으로 사용하지, Terraform으로는 사용하지 않아요:
modules,locals,variable블록이 없어요.- 표현식에서 사용 가능한 유일한 함수는
file()이에요; Terraform의 함수 라이브러리(file()을 vars 객체로 대체하는templatefile()포함)는 사용할 수 없어요. - 일반 리터럴 값: 문자열, 숫자, 불리언, 리스트, 객체, 중첩 블록을 선호해요.
- 변환 후 결과는 동등한 YAML 구성과 정확히 똑같이 검증돼요.
이미 Terraform을 안다면, Docker Agent HCL을 기존 구성 스키마 위의 얇은 블록 기반 구문으로 생각하세요.
예제 (Examples)
저장소에서 이 실제 구성들을 참고하세요:
- examples/pirate.hcl
- examples/gopher.hcl
- examples/instructions_from_file.hcl