> ## Documentation Index
> Fetch the complete documentation index at: https://docs.one.fim.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 환경 변수

> FIM One의 완전한 구성 참조.

모든 구성은 `.env`를 통해 수행됩니다. `example.env`를 복사하고 값을 입력하세요:

```bash theme={null}
cp example.env .env
```

## 설정 수준

각 통합에는 중요도를 나타내는 설정 수준이 있습니다:

| 수준     | 의미         | 설정되지 않았을 때의 동작                          |
| ------ | ---------- | --------------------------------------- |
| **필수** | 핵심 시스템 종속성 | 시스템 오류 발생 — 채팅 및 주요 기능이 작동하지 않음         |
| **권장** | 중요한 기능 활성화 | 우아한 성능 저하 — 기능이 명확하게 사용 불가능하지만 시스템은 실행됨 |
| **선택** | 향상 기능      | 투명한 성능 저하 — 시스템이 정상 작동하며, 기능만 없음        |

> **참고**: 관리자가 설정한 모델(관리자 → 모델 페이지)은 LLM 환경 변수를 대체할 수 있습니다. 상태 확인은 두 소스를 모두 고려합니다.

## 프론트엔드 (로컬 개발 전용)

프론트엔드에는 **로컬 개발 전용** 별도의 env 파일이 있습니다: `frontend/.env.local`.

> **이 파일은 Docker에서 사용되지 않습니다.** Docker 컨테이너 내에서 Next.js는 `/api/*`를 Python 백엔드로 내부적으로 프록시합니다 (포트 8000은 컨테이너 내부용이므로), 프론트엔드 env 파일이 필요하지 않습니다.

로컬 개발의 경우 기본값이 그대로 작동합니다 — 백엔드가 기본이 아닌 포트에서 실행되지 않는 한 `frontend/.env.local`을 생성할 **필요가 없습니다**.

필요한 경우 `frontend/.env.local`을 수동으로 생성하여 재정의할 수 있습니다:

```bash theme={null}
echo 'NEXT_PUBLIC_API_URL=http://localhost:9000' > frontend/.env.local
```

| 변수                    | 기본값                            | 설명                                                                                                                                      |
| --------------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| `NEXT_PUBLIC_API_URL` | `http://localhost:8000` *(자동)* | **브라우저**가 직접 API 호출(OAuth 리다이렉트, 스트리밍)에 사용하는 백엔드 URL입니다. 설정되지 않은 경우 `window.location`에서 자동 감지됩니다 — 백엔드가 로컬에서 비표준 포트에서 실행되는 경우에만 재정의하세요. |

> **빌드 타임 참고**: `NEXT_PUBLIC_*` 변수는 `pnpm build` 시점에 JS 번들에 포함됩니다. 런타임에 변경하는 것(예: 루트 `.env`를 통해)은 효과가 없습니다 — 이것이 로컬 개발 전용으로 `frontend/.env.local`에 있는 이유입니다.

***

## LLM (필수)

| 변수                                | 필수    | 기본값                                   | 설명                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| --------------------------------- | ----- | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `LLM_API_KEY`                     | **예** | —                                     | LLM 제공자의 API 키                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `LLM_BASE_URL`                    | 아니오   | `https://api.openai.com/v1`           | OpenAI 호환 API의 기본 URL                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `LLM_MODEL`                       | 아니오   | `gpt-4o`                              | 주 모델 — 계획, 분석, ReAct 에이전트에 사용됨                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `FAST_LLM_MODEL`                  | 아니오   | *(`LLM_MODEL`로 폴백)*                   | 빠른 모델 — DAG 단계 실행에 사용됨 (더 저렴하고 빠름)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `LLM_TEMPERATURE`                 | 아니오   | `0.7`                                 | 기본 샘플링 온도                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `LLM_CONTEXT_SIZE`                | 아니오   | `128000`                              | 주 LLM의 컨텍스트 윈도우 크기                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `LLM_MAX_OUTPUT_TOKENS`           | 아니오   | `64000`                               | 주 LLM의 호출당 최대 출력 토큰                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `FAST_LLM_API_KEY`                | 아니오   | *(`LLM_API_KEY`로 폴백)*                 | 빠른 모델 제공자의 API 키. 빠른 모델이 주 모델과 다른 제공자에서 호스팅될 때 사용                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `FAST_LLM_BASE_URL`               | 아니오   | *(`LLM_BASE_URL`로 폴백)*                | 빠른 모델 제공자의 기본 URL                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `FAST_LLM_TEMPERATURE`            | 아니오   | *(`LLM_TEMPERATURE`로 폴백)*             | 빠른 모델의 샘플링 온도                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `FAST_LLM_CONTEXT_SIZE`           | 아니오   | *(`LLM_CONTEXT_SIZE`로 폴백)*            | 빠른 LLM의 컨텍스트 윈도우 크기                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `FAST_LLM_MAX_OUTPUT_TOKENS`      | 아니오   | *(`LLM_MAX_OUTPUT_TOKENS`로 폴백)*       | 빠른 LLM의 호출당 최대 출력 토큰                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `LLM_REASONING_EFFORT`            | 아니오   | *(비활성화)*                              | 지원되는 모델의 확장 사고 수준 (OpenAI o-series, Gemini 2.5+, Claude). 값: `low`, `medium`, `high`. LiteLLM이 각 제공자의 네이티브 형식으로 자동 변환합니다. 모델의 사고 과정은 UI "thinking" 단계에서 표시됩니다.                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `LLM_REASONING_BUDGET_TOKENS`     | 아니오   | *(노력에서 자동)*                           | Anthropic 사고를 위한 명시적 토큰 예산 (최소 1024). OpenAI/Gemini의 경우 노력 수준이 직접 사용됩니다. `LLM_REASONING_EFFORT`가 설정되었을 때만 유효합니다.                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `FIM_GPT5_RESPONSES_MODE`         | 아니오   | `native`                              | GPT-5.x 모델이 사용하는 프로토콜. `native`는 OpenAI Responses API와 직접 통신하고 각 턴의 암호화된 추론을 재생하므로 모델이 도구 호출 전체에서 사고 과정을 유지합니다. `bridge`는 LiteLLM의 chat-completions 변환을 사용하며, 작동하지만 매 라운드마다 추론을 다시 도출합니다. `off`는 일반 chat completions를 강제하며, 도구가 있을 때마다 추론이 비활성화됩니다. `/v1/responses` 경로가 없는 엔드포인트는 자체적으로 폴백하지 않는 한 설정하지 마세요. GPT-5.x에만 적용됩니다.                                                                                                                                                                                                                                                              |
| `LLM_JSON_MODE_ENABLED`           | 아니오   | `true`                                | `response_format=json_object`의 전역 토글. 제공자가 LiteLLM의 어시스턴트 프리필 주입을 거부하는 경우 `false`로 설정하세요 (예: AWS Bedrock 릴레이 → 2번째 이상 에이전트 반복에서 `ValidationException`). 비활성화되면 구조화된 호출은 JSON 모드를 건너뛰고 일반 텍스트 정규식 추출로 폴백합니다 — 품질 손실 없음. 모든 모델 (ENV 구성 및 관리자 구성)에 적용됩니다.                                                                                                                                                                                                                                                                                                                                    |
| `LLM_TOOL_CHOICE_ENABLED`         | 아니오   | `true`                                | 구조화된 출력 추출에서 강제 `tool_choice`의 전역 토글 (레벨 1 — 네이티브 함수 호출). 모델이 강제 도구 선택으로 오류를 반환하는 경우 `false`로 설정하세요 (예: `tool_choice='specified'`를 거부하는 사고 모드 모델). 비활성화되면 구조화된 호출은 네이티브 FC를 건너뛰고 JSON 모드에서 시작합니다. 설정 → 모델 → 고급에서 모델별 재정의 가능.                                                                                                                                                                                                                                                                                                                                                              |
| `REASONING_LLM_MODEL`             | 아니오   | *(`LLM_MODEL`로 폴백)*                   | 추론 계층의 모델 이름. 깊은 분석이 필요한 작업에 사용됨 (예: DAG 계획, 계획 분석)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `REASONING_LLM_API_KEY`           | 아니오   | *(`LLM_API_KEY`로 폴백)*                 | 추론 모델 제공자의 API 키                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `REASONING_LLM_BASE_URL`          | 아니오   | *(`LLM_BASE_URL`로 폴백)*                | 추론 모델 제공자의 기본 URL                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `REASONING_LLM_TEMPERATURE`       | 아니오   | *(`LLM_TEMPERATURE`로 폴백)*             | 추론 모델의 샘플링 온도                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `REASONING_LLM_CONTEXT_SIZE`      | 아니오   | *(`LLM_CONTEXT_SIZE`로 폴백)*            | 추론 모델의 컨텍스트 윈도우 크기                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `REASONING_LLM_MAX_OUTPUT_TOKENS` | 아니오   | *(`LLM_MAX_OUTPUT_TOKENS`로 폴백)*       | 추론 모델의 호출당 최대 출력 토큰                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `REASONING_LLM_EFFORT`            | 아니오   | *(`LLM_REASONING_EFFORT`로 폴백)*        | 추론 모델 계층의 추론 노력 수준. 값: `low`, `medium`, `high`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `REASONING_LLM_BUDGET`            | 아니오   | *(`LLM_REASONING_BUDGET_TOKENS`로 폴백)* | 추론을 위한 토큰 예산 (주로 Anthropic). 추론 계층의 자동 계산 예산을 재정의합니다.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `LLM_SUPPORTS_VISION`             | 아니오   | `true` *(낙관적)*                        | ENV 모드 문서 OCR (MarkItDown + `markitdown-ocr`를 통해) 시도 여부를 제어합니다. **관리자 → 모델에서 활성 모델 그룹이 구성되지 않은 경우에만 적용됩니다** (순수 ENV 모드). 기본값 `true`가 적용되면 `convert_to_markdown`과 RAG 수집은 `LLM_MODEL`이 비전을 지원한다고 가정하고 이미지 OCR을 위해 호출합니다 — 이는 모든 일반적인 선택 (`gpt-4o`, `claude-3-5-sonnet`, `gemini-1.5-pro/flash`)에 대한 올바른 동작입니다. ENV 구성 `LLM_MODEL`이 비전을 지원하지 않는 경우 `false`로 설정하세요 (예: `deepseek-v3`, `qwen-chat`, `llama-3.1`, `gpt-3.5-turbo`, `o1-mini`) 실패한 비전 호출을 건너뛰고 텍스트 전용 추출로 직접 이동합니다. 관리자 → 모델 패널에 활성 모델 그룹이 있으면 이 플래그는 무시되고 그룹의 `supports_vision` 플래그가 우선합니다 — 관리자 선택은 항상 DB 모드의 신뢰할 수 있는 소스입니다. |

> **해석 순서**: 사용자 기본 설정 → 관리자 모델 (DB) → ENV 폴백. 관리자 → 모델에서 역할이 "General"인 관리자 모델이 구성된 경우, 이 ENV 변수는 폴백으로만 제공됩니다. 상태 확인은 두 소스를 모두 고려합니다.

### MarkItDown OCR 해상도

`convert_to_markdown` 내장 도구와 RAG 수집 파이프라인은 모두 Microsoft의 [MarkItDown](https://github.com/microsoft/markitdown) + 공식 [`markitdown-ocr`](https://github.com/microsoft/markitdown/tree/main/packages/markitdown-ocr) 플러그인을 사용하여 문서에서 텍스트를 추출합니다 — 비전 기능이 있는 LLM을 사용할 수 있을 때 임베드된 이미지와 스캔된 PDF 페이지에 대한 OCR을 포함합니다.

**비전 LLM 해상도 순서** (첫 번째 일치 우선):

| # | 소스                                                             | 우선순위 근거                                                                                                   |
| - | -------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| 1 | 에이전트의 **기본 LLM** (`supports_vision=True`인 경우)                  | 일관성: 동일한 API 키, 동일한 청구 버킷, 대화와 동일한 속도 제한 풀.                                                               |
| 2 | 활성 **ModelGroup → Fast Model** (`supports_vision=True`인 경우)    | Fast 모델(`gpt-4o-mini`, `claude-haiku`, `gemini-1.5-flash`)은 이상적인 OCR 워크호스입니다 — 저렴하고, 낮은 지연시간, 보통 멀티모달입니다. |
| 3 | 활성 **ModelGroup → General Model** (`supports_vision=True`인 경우) | 기본 모델이 그룹에 없을 때의 품질 폴백입니다.                                                                                |
| 4 | **ENV 기본 LLM** (`LLM_MODEL`)                                   | 순수 ENV 모드에 대한 낙관적 폴백입니다. 활성 ModelGroup이 없을 때만 사용됩니다. `LLM_SUPPORTS_VISION`으로 제어됩니다.                       |

**추론 모델은 OCR에 선호되지 않습니다.** 추론 계층(`o1`, `o3-mini`, `DeepSeek-R1`)은 역사적으로 비전 지원이 부족하며 OCR에는 잘못된 도구입니다 — OCR은 인식 작업이지 숙고 작업이 아닙니다. 워크스페이스에 `supports_vision=True`인 추론 모델만 있는 경우 기본 LLM 경로를 통해 여전히 선택되지만, 리졸버는 fast/general보다 높게 순위를 매기지 않습니다.

**제로 회귀 폴백**: 어떤 수준에서도 비전 기능이 있는 모델을 찾을 수 없을 때, OCR은 자동으로 비활성화되고 MarkItDown은 텍스트 전용 모드에서 실행됩니다. Word/PowerPoint/Excel 임베드된 이미지 OCR은 사용할 수 없게 됩니다(이 기능이 출시되기 전과 동일), 하지만 다른 모든 텍스트 추출(제목, 표, 단락 텍스트)은 변경 없이 계속 작동합니다. **이 기능을 추가하여 추출이 이전 동작보다 악화된 경우는 절대 없습니다.**

\*\*OpenAI가 아닌 제공자(Anthropic, Google Gemini 등)\*\*는 투명하게 지원됩니다: 해석된 LLM은 `LiteLLMOpenAIShim`으로 래핑되어 `chat.completions.create(...)` 호출을 `litellm.completion()`을 통해 라우팅하며, 이는 제공자별 메시지 형식 변환(예: Anthropic의 `source.type="base64"` 이미지 블록)을 처리합니다. 하나의 shim은 LiteLLM이 지원하는 모든 제공자를 포함합니다 — 새로운 제공자를 추가하는 데 FIM One에서 코드 변경이 필요하지 않습니다.

### 확장 사고 (추론)

`LLM_REASONING_EFFORT`가 설정되면 FIM One은 모델의 확장 사고 기능을 활성화하여 내부 사고의 연쇄가 UI의 "thinking" 단계에 표시됩니다. FIM One은 [LiteLLM](https://github.com/BerriAI/litellm)을 사용하여 추론 노력 매개변수를 각 제공자의 기본 형식으로 자동으로 변환합니다.

#### 지원되는 제공자

어떤 제공자가 thinking을 수용하는지, 각각을 어떻게 활성화하는지, 어떤 `effort` 값을 사용하는지, 그리고 reasoning 텍스트가 어디에 끝나는지는 [Provider Capability Matrix의 표 C](/architecture/llm-provider-guide#provider-capability-matrix)에 코드 앵커와 함께 한 번만 기록됩니다. 그 표가 권위 있는 목록이며, 이 페이지는 변수만 문서화합니다.

FIM One은 `LLM_BASE_URL`에서 제공자를 해석하고(구성된 경우 명시적 제공자 필드 포함) 요청을 올바른 API 형식으로 매핑합니다. 알 수 없는 URL은 OpenAI 호환으로 처리됩니다.

#### 중요한 주의사항

<Warning>
  **타사 프록시 / 사용자 정의 엔드포인트는 보장되지 않습니다.**
  `LLM_BASE_URL`이 타사 API 프록시(예: OpenRouter, one-api, 사용자 정의 게이트웨이)를 가리키는 경우, LiteLLM은 URL을 기반으로 올바르게 라우팅하려고 시도합니다. 그러나 프록시가 비표준 형식을 예상하는 경우 추론이 예상대로 작동하지 않을 수 있습니다. 프록시의 예상 매개변수 형식에 대해서는 프록시의 설명서를 참조하세요.
</Warning>

#### 추론을 사용할 때의 온도 제약

일부 제공자는 추론이 활성화되었을 때 `temperature`를 제한합니다. **이러한 제약은 모두 자동으로 적용되므로 `LLM_TEMPERATURE`는 워크로드에 맞는 값으로 설정하면 됩니다.**

* **Anthropic**: 확장 사고가 활성화되어 있을 때 `temperature=1`을 요구합니다. 요청 빌더가 Anthropic 경로에서 값을 고정하므로 요청이 거부되지 않고 설정된 온도가 해당 호출에 대해 재정의됩니다.
* **Anthropic, 엄격한 모델**(Opus 4.7 및 4.8, Fable 5, Mythos 5): 사고 여부와 관계없이 `temperature`, `top_p`, `top_k`를 완전히 거부합니다. FIM One은 이러한 모델에 대해 요청에서 `temperature`를 제거합니다.
* **OpenAI GPT-5.x**: `temperature=1`만 지원합니다. LiteLLM의 `drop_params` 필터링이 지원되지 않는 값을 제거합니다.

Anthropic을 만족시키기 위해 `LLM_TEMPERATURE=1`을 수동으로 설정하는 것은 불필요하며, 사고하지 않는 모든 호출에서 더 낮은 온도를 실행할 수 있는 능력을 잃게 됩니다.

#### `LLM_REASONING_BUDGET_TOKENS` 작동 방식

이 변수는 **레거시 Anthropic 사고 경로에서만 의미가 있습니다**(Claude 4.5 이하, `anthropic/`으로 라우팅됨). 여기서 자동 계산된 예산을 재정의하고 `thinking` 매개변수 내에서 `budget_tokens`로 전송됩니다. 적응형 사고 모델(Opus 4.6 이상, Sonnet 4.6, Fable 5, Mythos 5)은 예산 대신 노력 수준을 사용하며 이 변수를 완전히 무시합니다. 설정되지 않으면 예산은 `LLM_MAX_OUTPUT_TOKENS` x 노력 비율에서 파생됩니다:

| `LLM_REASONING_EFFORT` | 예산 비율 | 예시 (max\_tokens = 64000) |
| ---------------------- | ----- | ------------------------ |
| `low`                  | 20%   | 12,800 tokens            |
| `medium`               | 50%   | 32,000 tokens            |
| `high`                 | 80%   | 51,200 tokens            |

최소 예산은 1,024 tokens입니다(Anthropic의 하드 최소값).

OpenAI 및 Gemini의 경우, 제공자가 `reasoning_effort` 수준에 따라 토큰 할당을 내부적으로 처리합니다 — `LLM_REASONING_BUDGET_TOKENS`는 효과가 없습니다.

## 에이전트 실행

### ReAct 에이전트

| 변수                                  | 필수  | 기본값     | 설명                                                                                                                                                                                                                                                                                           |
| ----------------------------------- | --- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `REACT_MAX_ITERATIONS`              | 아니오 | `20`    | ReAct 요청당 최대 도구 호출 반복 횟수. 높을수록 더 철저하지만 느리고 비용이 많이 듦                                                                                                                                                                                                                                          |
| `REACT_MAX_TURN_TOKENS`             | 아니오 | `0`     | 긴급 차단기: 단일 ReAct 턴당 최대 누적 토큰(모든 반복에 걸친 프롬프트 + 완료). 기본값 `0` = 무제한. **이는 일일 토큰 제어용이 아님** — 일일 토큰 제어는 사용자별 `token_quota`를 사용하세요. 이는 에이전트가 무한 도구 호출 루프에 갇혀 있는 등의 극단적인 시나리오에 대한 최후의 안전 장치입니다. 이 제한에 도달하면 작업이 중간에 중단되어 지금까지 소비된 모든 토큰이 낭비되고 불완전한 결과가 반환됩니다. 특정 폭주 에이전트 문제가 있을 때만 `0`이 아닌 값으로 설정하세요 |
| `REACT_TOOL_SELECTION_THRESHOLD`    | 아니오 | `12`    | 등록된 도구의 총 개수가 이 임계값을 초과할 때, 각 요청 전에 경량 LLM 호출이 가장 관련성 높은 부분 집합을 선택함                                                                                                                                                                                                                          |
| `REACT_TOOL_SELECTION_MAX`          | 아니오 | `6`     | 스마트 선택 후 유지할 최대 도구 개수(도구 개수가 `REACT_TOOL_SELECTION_THRESHOLD`를 초과할 때만 적용)                                                                                                                                                                                                                    |
| `REACT_SELF_REFLECTION_INTERVAL`    | 아니오 | `6`     | N번의 도구 호출마다 자기 성찰 프롬프트를 주입하여 에이전트가 방향을 수정하고 루프를 피하도록 도움                                                                                                                                                                                                                                      |
| `REACT_TOOL_OBS_TRUNCATION`         | 아니오 | `8000`  | 최종 답변을 합성할 때 도구 관찰당 최대 문자 수. 더 높은 값은 더 많은 구조화된 데이터(JSON, 표)를 보존하지만 더 많은 토큰을 소비함                                                                                                                                                                                                              |
| `REACT_TOOL_RESULT_BUDGET`          | 아니오 | `40000` | 단일 세션의 모든 도구 결과에 대한 집계 토큰 예산. 도구 결과 토큰의 총합이 이 상한을 초과하면 새 결과는 알림과 함께 잘림. 대규모 API 응답(예: 각각 8K를 반환하는 5개의 커넥터 호출)으로 인한 컨텍스트 팽창을 방지함. 상한을 비활성화하려면 `0`으로 설정                                                                                                                                        |
| `REACT_COMPLETION_CHECK_SKIP_CHARS` | 아니오 | `800`   | 에이전트의 최종 답변이 이 많은 문자를 초과할 때 사후 답변 완료 확인 LLM 호출을 건너뜀. 길고 상세한 답변은 "뭔가 놓친 게 있나?" 검증 왕복이 필요 없음. 더 낮게 설정하면 더 적극적으로 건너뜀; 매우 큰 값으로 설정하면 항상 확인을 실행                                                                                                                                                   |
| `REACT_CYCLE_DETECTION_THRESHOLD`   | 아니오 | `2`     | 동일한 인수로 같은 도구를 이 횟수만큼 연속으로 호출할 때, 결정론적 경고가 주입되어 에이전트에게 다른 접근 방식을 시도하도록 지시함. 자기 성찰(LLM이 루프를 인식하는 데 의존)과 달리 이는 우회할 수 없는 해시 기반 확인. DAG 단계에도 적용됨                                                                                                                                                 |
| `REACT_COMPLETION_CHECK_MIN_TOOLS`  | 아니오 | `3`     | 완료 체크리스트가 실행되기 전의 최소 도구 호출 횟수. 간단한 작업(1-2개 도구 호출)은 불필요한 지연을 피하기 위해 검증을 건너뜀. 항상 검증을 실행하려면 `1`로 설정. DAG 단계에도 적용됨                                                                                                                                                                               |
| `REACT_TURN_PROFILE_ENABLED`        | 아니오 | `true`  | 턴별 단계 수준 타이밍 로그(`memory_load`, `compact`, `tool_schema_build`, `llm_first_token`, `llm_total`, `tool_exec`) 내보내기. 턴당 하나의 구조화된 로그 라인. 프로파일링을 완전히 비활성화하려면 `false`로 설정(오버헤드 없음)                                                                                                                 |
| `REACT_PLAN_TOOL_ENABLED`           | 아니오 | `true`  | `update_plan` 할일 도구를 등록하여 에이전트가 다단계 작업 중에 계획 체크리스트를 작성하고 유지할 수 있도록 함. DAG 단계 에이전트 및 도구가 없는 에이전트의 경우 자동으로 건너뜀                                                                                                                                                                                 |
| `REACT_PLAN_REMINDER_INTERVAL`      | 아니오 | `3`     | `update_plan` 호출 없이 오래된 계획 미리 알림이 다시 주입되기 전의 도구 라운드 수(전체 체크리스트 포함). 계획이 컨텍스트 압축을 견디도록 함                                                                                                                                                                                                      |
| `REACT_PLAN_REPEAT_THRESHOLD`       | 아니오 | `4`     | 에이전트에게 무익한 호출을 반복하는 대신 접근 방식을 변경하도록 지시하는 미리 알림이 나오기 전에 같은 도구를 호출하는 연속 라운드 수(다른 인수 사용). 정확히 중복된 호출은 사이클 감지에 의해 별도로 처리됨                                                                                                                                                                        |
| `REACT_PLAN_NUDGE_AFTER`            | 아니오 | `5`     | 계획이 기록되지 않은 도구 라운드 수. 계획 작성을 제안하는 일회성 미리 알림이 나옴. 계획 도구가 활성화된 경우에만 적용됨                                                                                                                                                                                                                        |
| `REACT_FINISH_SIGNAL`               | 아니오 | `true`  | 채팅 경로에서 FINAL 우선 답변: 에이전트가 `finish` 신호에서 도구 루프를 종료한 후 답변을 진정한 토큰 스트리밍 턴으로 작성함. `false`로 설정하면 버퍼된 재생과 함께 인라인 루프 답변으로 복원                                                                                                                                                                       |
| `REACT_MAX_CONTINUATIONS`           | 아니오 | `3`     | 모델의 답변이 제공자의 출력 토큰 제한(`finish_reason=length`)으로 인해 잘릴 때의 최대 연속 라운드 수. 잘린 세그먼트는 에이전트 루프와 스트리밍 합성 모두에서 하나의 매끄러운 답변으로 연결됨                                                                                                                                                                       |
| `REACT_BACKGROUND_TOOLS_ENABLED`    | 아니오 | `true`  | 느린 도구(샌드박스 python/shell/node 실행)에 `run_in_background` 옵션 제공. 에이전트는 즉시 작업 ID를 받고 계속 작업하며, 도구가 완료되면 결과가 `<task_notification>` 메시지로 도착                                                                                                                                                          |
| `REACT_BG_WAIT_TIMEOUT`             | 아니오 | `300`   | 에이전트가 답변을 최종화하려고 할 때 여전히 실행 중인 백그라운드 도구를 기다릴 최대 초 수. 시간 창 내에 완료되지 않은 작업은 명시적 타임아웃 알림과 함께 취소됨                                                                                                                                                                                                 |
| `DAG_CHECKPOINT_EVIDENCE_CHARS`     | 아니오 | `4000`  | DAG 충돌 복구 체크포인트 파일(`data/dag_checkpoints/`)의 단계별 증거 상한. 단계 요약은 전체 저장됨                                                                                                                                                                                                                        |
| `DAG_CHECKPOINT_MAX_AGE_HOURS`      | 아니오 | `24`    | 이보다 오래된 DAG 체크포인트는 로드 시 무시되므로 오래된 충돌 잔여물이 새 실행으로 복구되지 않음                                                                                                                                                                                                                                     |
| `LLM_RATE_LIMIT_PER_USER`           | 아니오 | `true`  | 단일 프로세스 전역 버킷 대신 사용자별 키 지정 속도 제한 버킷을 사용. 한 명의 시끄러운 사용자가 같은 워커의 다른 모든 사용자를 굶기는 것을 방지함. 기본 속도는 버킷당 분당 60개 요청 및 분당 100K 토큰으로 하드코딩됨 — 이 설정은 버킷이 공유(전역)인지 분할(사용자별)인지만 제어함. 레거시 전역 버킷으로 되돌리려면 `false`로 설정(권장하지 않음)                                                                                 |

### DAG Planner

| Variable                         | Required | Default | Description                                                                                                                                                                                                                                                              |
| -------------------------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `MAX_CONCURRENCY`                | No       | `5`     | DAG 실행기에서 병렬 처리할 수 있는 최대 단계 수                                                                                                                                                                                                                                            |
| `DAG_STEP_MAX_ITERATIONS`        | No       | `15`    | 각 DAG 단계 내에서 도구 호출의 최대 반복 횟수                                                                                                                                                                                                                                             |
| `DAG_STEP_TIMEOUT`               | No       | `600`   | 단계 실행 타임아웃(초). 이를 초과하는 단계는 실패로 표시되고 종속 단계는 연쇄 스킵됨                                                                                                                                                                                                                        |
| `DAG_MAX_REPLAN_ROUNDS`          | No       | `3`     | 목표 달성 실패 시 자동 재계획 시도의 최대 횟수. 사용자 중단(주입)은 무제한이며 이 예산에 포함되지 않음                                                                                                                                                                                                             |
| `DAG_REPLAN_STOP_CONFIDENCE`     | No       | `0.8`   | 에이전트가 목표를 **도달 불가능**하다고 판단할 때만 적용(불가능한 요청, 누락된 기능, 사용 불가능한 리소스): 이 확신도 이상에서 재시도 중지. 미완성 또는 부분 완성된 결과물은 항상 재계획되며, 확신도와 관계없이 `DAG_MAX_REPLAN_ROUNDS`만 이러한 재시도를 제한함                                                                                                         |
| `DAG_VERIFY_TRUNCATION`          | No       | `2000`  | 단계 품질 판단을 위해 단계 검증기 LLM으로 전송되는 단계 출력의 최대 문자 수                                                                                                                                                                                                                            |
| `DAG_ANALYZER_TRUNCATION`        | No       | `10000` | 실행 후 분석기로 포맷팅할 때 단계 결과당 최대 문자 수                                                                                                                                                                                                                                          |
| `DAG_STEP_EVIDENCE_CHARS`        | No       | `16000` | 단계당 보존되는 원본 도구 출력(웹 페칭, 검색 결과, 파일 읽기)의 최대 문자 수로, 권위 있는 "소스 증거"로 사용됨. 이는 분석기 및 최종 합성과 함께 단계의 자체 요약과 함께 제공되므로 답변의 사실적 주장(합계, 열거, 심각도)을 요약이 자동으로 삭제하거나 잘못 표시했을 수 있는 항목 대신 소스에 대해 검증할 수 있음. 증거 캡처를 비활성화하려면 `0`으로 설정                                                          |
| `DAG_REPLAN_RECENT_TRUNCATION`   | No       | `500`   | 재계획 컨텍스트 구축 시 가장 최근 라운드의 단계 결과당 최대 문자 수                                                                                                                                                                                                                                  |
| `DAG_REPLAN_OLDER_TRUNCATION`    | No       | `200`   | 재계획 컨텍스트 구축 시 이전 라운드의 단계 결과당 최대 문자 수. 이전 라운드는 컨텍스트를 절약하기 위해 더 적극적으로 잘림                                                                                                                                                                                                   |
| `DAG_TOOL_CACHE`                 | No       | `true`  | 단일 DAG 실행 내에서 동일한 도구 호출 캐시. `cacheable`로 명시적으로 표시된 도구(검색, 지식 검색 같은 읽기 전용 도구)만 캐시됨. 캐싱을 완전히 비활성화하려면 `false`로 설정                                                                                                                                                           |
| `DAG_STEP_VERIFICATION`          | No       | `false` | 각 DAG 단계 후 일반 LLM 기반 품질 확인. 실패 시 단계는 피드백과 함께 한 번 재시도됨. **기본값 해제** — 모든 단계에 지연을 추가하며 거의 필요하지 않음. 대부분의 단계 출력은 재확인 없이 허용됨. 단계 결과 품질이 낮은 경우가 자주 관찰될 때만 사용                                                                                                                    |
| `DAG_CITATION_VERIFICATION`      | No       | `true`  | 전문 도메인 단계에 대한 인용 정확성 확인. **전제 조건**: 쿼리는 먼저 LLM 도메인 분류기에 의해 전문 도메인으로 분류되어야 함(`ESCALATION_DOMAINS` 참조). 도메인이 감지되고 이 플래그가 `true`일 때, 완료된 각 단계는 법률/의료/금융 인용에 대해 스캔되고 정확성이 검증됨 — 환각된 문서 번호, 조작된 사건 참조, 잘못된 규제 인용을 포착함. 도메인 분류가 `null`을 반환하면(일반 쿼리), 이 설정과 관계없이 인용 검증이 실행되지 않음 |
| `DAG_CITATION_VERIFY_TRUNCATION` | No       | `6000`  | 인용 검증 프롬프트로 전송되는 단계 결과의 최대 문자 수                                                                                                                                                                                                                                          |

### 도메인 분류

ReAct 및 DAG 실행 **이전**에 실행되는 독립적인 LLM 기반 도메인 감지 레이어를 제어합니다. 쿼리가 전문 도메인으로 분류되면 시스템은 도메인 인식 기능을 활성화합니다: 추론 모델로의 모델 에스컬레이션, 도메인별 SOP 지침, 인용 검증(DAG만 해당).

| 변수                   | 필수  | 기본값                                             | 설명                                                                                                                                                                                                                         |
| -------------------- | --- | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ESCALATION_DOMAINS` | 아니요 | `legal,medical,financial,tax,compliance,patent` | 전문 도메인의 쉼표로 구분된 목록입니다. 빠른 LLM이 각 쿼리를 이 목록에 대해 분류합니다. 일치하면 시스템은: (1) 더 높은 정확도를 위해 추론 모델로 업그레이드, (2) 도메인별 SOP 지침 주입(예: 작성 전 검색을 통해 인용 검증), (3) DAG 단계에 대한 인용 검증 활성화. 필요에 따라 사용자 정의 도메인 추가(예: `legal,education,construction`) |

### Context Guard

대화가 모델의 한계를 초과하지 않도록 방지하는 자동 컨텍스트 윈도우 관리를 제어합니다.

| Variable                       | Required | Default | Description                                            |
| ------------------------------ | -------- | ------- | ------------------------------------------------------ |
| `CONTEXT_GUARD_DEFAULT_BUDGET` | No       | `32000` | 컨텍스트 윈도우 관리를 위한 기본 토큰 예산입니다. 대화가 이를 초과하면 이전 메시지가 압축됩니다 |
| `CONTEXT_GUARD_MAX_MSG_CHARS`  | No       | `50000` | 단일 메시지의 하드 문자 제한입니다. 이를 초과하는 메시지는 안전 장치로 잘립니다          |
| `CONTEXT_GUARD_KEEP_RECENT`    | No       | `4`     | 대화 기록을 압축할 때 보존할 가장 최근 메시지의 개수입니다                      |

### Content Guardrails

콘텐츠를 검사하는 가드레일의 쉼표로 구분된 이름입니다. 도구 권한 게이트(`core/hooks/*`)와 보안 계층(`core/security/*`)과는 독립적입니다. 전체 그림은 [Content Guardrails](/configuration/guardrails)를 참조하세요.

| Variable                         | Required | Default     | Description                                                                                                                     |
| -------------------------------- | -------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `FIM_GUARDRAILS_INPUT`           | No       | `jailbreak` | 활성 입력 가드레일입니다. 기본값인 `jailbreak` 정규식 감지기는 알려진 프롬프트 오버라이드 구문이 감지되면 LLM 토큰이 소비되기 전에 턴을 중단합니다. 비활성화하려면 비워두세요. 알 수 없는 이름은 로깅되고 건너뜁니다 |
| `FIM_GUARDRAILS_OUTPUT`          | No       | (empty)     | 활성 출력 가드레일입니다. 현재 제공: `max_length`(답변 문자 수 제한). 에이전트가 최종 답변을 생성한 후 실행됩니다                                                        |
| `FIM_GUARDRAIL_MAX_OUTPUT_CHARS` | No       | `50000`     | `max_length` 출력 가드레일에서 사용하는 문자 제한입니다. `FIM_GUARDRAILS_OUTPUT`에 `max_length`가 나열되어 있을 때만 적용됩니다                                   |

### 에이전트 워크스페이스

| 변수                            | 필수  | 기본값    | 설명                                                          |
| ----------------------------- | --- | ------ | ----------------------------------------------------------- |
| `WORKSPACE_OFFLOAD_THRESHOLD` | 아니오 | `8000` | 도구 출력이 이 문자 수를 초과하면 워크스페이스 파일에 저장되고 잘린 미리보기가 대화 컨텍스트에 주입됩니다 |
| `WORKSPACE_PREVIEW_CHARS`     | 아니오 | `2000` | 잘린 워크스페이스 참조에 포함할 미리보기 문자 수                                 |
| `WORKSPACE_CLEANUP_MAX_HOURS` | 아니오 | `72`   | 이 시간보다 오래된 워크스페이스 파일은 자동 정리 대상입니다                           |

### System

| Variable                    | Required | Default | Description                                                                                                                                                                                                                   |
| --------------------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ~~`SYSTEM_PROMPT_RESERVE`~~ | —        | —       | **제거됨.** 이전에는 시스템 프롬프트를 위해 컨텍스트 예산에서 고정 4K를 차감했습니다. ContextGuard가 이미 메시지 목록 토큰을 추정할 때 시스템 프롬프트를 포함하므로 이중 계산이 발생했습니다. 예산 공식은 이제 `(context_size - max_output_tokens) × 0.92`입니다(여백은 토큰 추정 오류를 흡수함). 시스템 프롬프트의 실제 크기는 동적으로 계산됩니다 |

## 웹 도구 (선택사항)

| 변수                    | 필수  | 기본값                                 | 설명                                                                                                                                                       |
| --------------------- | --- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `JINA_API_KEY`        | 아니오 | —                                   | Jina API 키. **기본** 검색 백엔드를 구동하며, 서비스별 키가 설정되지 않았을 때 **fetch, embedding, reranker**의 공유 폴백으로 작동합니다. [jina.ai](https://jina.ai/)에서 발급받으세요                  |
| `TAVILY_API_KEY`      | 아니오 | —                                   | Tavily Search API 키. `WEB_SEARCH_PROVIDER=tavily`일 때 필수이며, 제공자가 설정되지 않았을 때 자동 감지에서도 사용됩니다                                                                |
| `BRAVE_API_KEY`       | 아니오 | —                                   | Brave Search API 키. `WEB_SEARCH_PROVIDER=brave`일 때 필수이며, 제공자가 설정되지 않았을 때 자동 감지에서도 사용됩니다                                                                  |
| `EXA_API_KEY`         | 아니오 | —                                   | Exa Search API 키. `WEB_SEARCH_PROVIDER=exa`일 때 필수이며, 제공자가 설정되지 않았을 때 자동 감지에서도 사용됩니다. [Exa](/integrations/exa)를 참조하세요. [exa.ai](https://exa.ai/)에서 발급받으세요 |
| `WEB_SEARCH_PROVIDER` | 아니오 | `jina`                              | 검색 제공자 선택: `jina` (기본값) / `tavily` / `brave` / `exa`. 기본값이 아닌 제공자를 사용할 때는 명시적으로 설정하는 것을 권장합니다                                                            |
| `WEB_FETCH_PROVIDER`  | 아니오 | `jina` (키가 설정된 경우, 그렇지 않으면 `httpx`) | Fetch 제공자: `jina` (Jina Reader API 사용) / `httpx` (직접 HTTP 요청, API 키 불필요)                                                                                 |

> **빠른 시작 팁**: `JINA_API_KEY`만 설정하면 기본 웹 검색 스택, 웹 fetch, embedding, reranking을 활성화할 수 있습니다 — 하나의 키로 네 가지 서비스를 이용할 수 있습니다. `WEB_SEARCH_PROVIDER`와 일치하는 API 키로 검색을 Tavily, Brave 또는 Exa로 전환하세요.

## RAG 및 지식 기반 (권장)

### 임베딩

임베딩은 텍스트를 벡터로 변환하여 지식 기반 검색에 사용합니다. FIM One은 표준 **OpenAI 호환 `/v1/embeddings` 엔드포인트**를 사용하므로, Jina뿐만 아니라 이 인터페이스를 제공하는 모든 제공자와 함께 작동합니다.

| 변수                    | 필수  | 기본값                              | 설명              |
| --------------------- | --- | -------------------------------- | --------------- |
| `EMBEDDING_API_KEY`   | 아니요 | *(falls back to `JINA_API_KEY`)* | 임베딩 제공자의 API 키  |
| `EMBEDDING_BASE_URL`  | 아니요 | `https://api.jina.ai/v1`         | 임베딩 제공자의 기본 URL |
| `EMBEDDING_MODEL`     | 아니요 | `jina-embeddings-v3`             | 모델 식별자          |
| `EMBEDDING_DIMENSION` | 아니요 | `1024`                           | 벡터 차원           |

**제공자 예시** — 세 변수를 설정하여 전환하세요:

| 제공자               | `EMBEDDING_BASE_URL`          | `EMBEDDING_MODEL`        | `EMBEDDING_DIMENSION` |
| ----------------- | ----------------------------- | ------------------------ | --------------------- |
| **Jina** *(기본값)*  | `https://api.jina.ai/v1`      | `jina-embeddings-v3`     | `1024`                |
| **OpenAI**        | `https://api.openai.com/v1`   | `text-embedding-3-small` | `1536`                |
| **Voyage**        | `https://api.voyageai.com/v1` | `voyage-3`               | `1024`                |
| **Ollama** *(로컬)* | `http://localhost:11434/v1`   | `nomic-embed-text`       | `768`                 |

<Warning>
  **임베딩 모델 또는 차원을 변경하면 기존의 모든 지식 기반 벡터가 무효화됩니다.** 이전 벡터는 다른 임베딩 공간에서 계산되었으므로 검색 정확도가 조용히 저하될 것입니다. 전환 후 **모든 지식 기반 인덱스를 다시 구축해야 합니다**.
</Warning>

### 검색

| 변수               | 필수  | 기본값         | 설명                                                           |
| ---------------- | --- | ----------- | ------------------------------------------------------------ |
| `RETRIEVAL_MODE` | 아니오 | `grounding` | `grounding` (인용 및 신뢰도 점수가 포함된 전체 파이프라인) 또는 `simple` (기본 RAG) |

### Reranker

Reranker는 검색된 문서를 다시 점수 매겨 관련성을 개선합니다. 세 가지 공급자가 지원되며 `RERANKER_PROVIDER`를 통해 선택하거나 시스템이 사용 가능한 API 키에서 자동 감지하도록 할 수 있습니다.

| Variable                | Required | Default                              | Description                                                                                    |
| ----------------------- | -------- | ------------------------------------ | ---------------------------------------------------------------------------------------------- |
| `RERANKER_PROVIDER`     | No       | *(auto-detect)*                      | `jina` / `cohere` / `openai`. 설정하지 않으면: `COHERE_API_KEY`가 설정된 경우 Cohere를 사용하고, 그렇지 않으면 Jina 사용 |
| `RERANKER_MODEL`        | No       | `jina-reranker-v2-base-multilingual` | 모델 식별자 (Jina 및 OpenAI 공급자에 적용)                                                                 |
| `COHERE_API_KEY`        | No       | —                                    | Cohere API 키 (설정되고 `RERANKER_PROVIDER`가 설정되지 않은 경우 Cohere reranker 자동 선택)                      |
| `COHERE_RERANKER_MODEL` | No       | `rerank-multilingual-v3.0`           | Cohere 전용 reranker 모델                                                                          |

> **Jina**는 `JINA_API_KEY`를 사용합니다 (위의 Web Tools에서). **OpenAI**는 `LLM_API_KEY` / `LLM_BASE_URL`을 재사용합니다 — 추가 키가 필요하지 않습니다. **Cohere**는 자체 `COHERE_API_KEY`가 필요합니다.

> Reranker는 **선택 사항**입니다 — 지식 베이스 검색은 fusion 점수 매기기를 사용하여 이 없이도 작동합니다. Embedding은 지식 베이스 기능에 **권장**됩니다.

### 벡터 저장소

| 변수                 | 필수  | 기본값                   | 설명                                          |
| ------------------ | --- | --------------------- | ------------------------------------------- |
| `VECTOR_STORE_DIR` | 아니요 | `./data/vector_store` | LanceDB 벡터 저장소 데이터용 디렉토리 (파일 기반, 외부 서비스 없음) |

***

## 코드 실행

| 변수                     | 필수  | 기본값                | 설명                                                                                                                         |
| ---------------------- | --- | ------------------ | -------------------------------------------------------------------------------------------------------------------------- |
| `CODE_EXEC_BACKEND`    | 아니오 | `local`            | `local` (직접 호스트 실행) 또는 `docker` (격리된 컨테이너)                                                                                 |
| `DOCKER_PYTHON_IMAGE`  | 아니오 | `python:3.11-slim` | Python 실행용 Docker 이미지                                                                                                      |
| `DOCKER_NODE_IMAGE`    | 아니오 | `node:20-slim`     | Node.js 실행용 Docker 이미지                                                                                                     |
| `DOCKER_SHELL_IMAGE`   | 아니오 | `python:3.11-slim` | 셸 실행용 Docker 이미지                                                                                                           |
| `DOCKER_MEMORY`        | 아니오 | *(Docker 기본값)*     | 컨테이너당 RAM 제한 (예: `256m`, `512m`, `1g`)                                                                                     |
| `DOCKER_CPUS`          | 아니오 | *(Docker 기본값)*     | 컨테이너당 CPU 할당량 (예: `0.5`, `1.0`)                                                                                            |
| `SANDBOX_TIMEOUT`      | 아니오 | `120`              | 기본 실행 타임아웃(초)                                                                                                              |
| `DOCKER_HOST_DATA_DIR` | 아니오 | *(설정되지 않음)*        | `./data` 볼륨 마운트의 호스트 측 절대 경로. DooD(Docker-outside-of-Docker) 배포에 필수이며, `docker-compose.yml`은 `${PWD}/data`를 통해 자동으로 설정합니다. |

> **보안**: `local` 모드는 AI가 생성한 코드를 호스트에서 직접 실행합니다. 인터넷 공개 또는 다중 사용자 배포의 경우, 항상 `CODE_EXEC_BACKEND=docker`로 설정하세요.

***

## 도구 아티팩트

도구 실행(코드 실행, 템플릿 렌더링, 이미지 생성)으로 생성된 파일의 크기 제한입니다.

| 변수                    | 필수  | 기본값                | 설명                     |
| --------------------- | --- | ------------------ | ---------------------- |
| `MAX_ARTIFACT_SIZE`   | 아니오 | `10485760` (10 MB) | 단일 아티팩트 파일의 최대 크기(바이트) |
| `MAX_ARTIFACTS_TOTAL` | 아니오 | `52428800` (50 MB) | 세션당 총 아티팩트의 최대 크기(바이트) |

***

## 문서 처리 (선택사항)

업로드된 PDF/DOCX 파일이 LLM 사용을 위해 어떻게 처리되는지를 제어합니다. 비전 기능이 있는 모델(GPT-4o, Claude 3/4, Gemini)은 더 높은 충실도를 위해 PDF 페이지를 렌더링된 이미지로 받을 수 있습니다.

| 변수                          | 필수  | 기본값    | 설명                                                               |
| --------------------------- | --- | ------ | ---------------------------------------------------------------- |
| `DOCUMENT_PROCESSING_MODE`  | 아니오 | `auto` | `auto` (모델이 지원하면 비전), `vision` (항상 페이지 렌더링), `text` (항상 텍스트만 추출) |
| `DOCUMENT_VISION_DPI`       | 아니오 | `150`  | PDF 페이지 렌더링을 위한 DPI. 높을수록 = 더 나은 품질, 더 많은 토큰                     |
| `DOCUMENT_VISION_MAX_PAGES` | 아니오 | `20`   | PDF당 이미지로 렌더링할 최대 페이지 수                                          |

> **참고**: 모델별 비전 지원은 관리자 → 모델의 `supports_vision` 토글을 통해 구성됩니다. 명시적으로 설정되지 않으면 시스템이 모델 이름에서 비전 기능을 자동으로 감지합니다.

***

## 이미지 생성 (선택사항)

| 변수                   | 필수  | 기본값                              | 설명                                                                                              |
| -------------------- | --- | -------------------------------- | ----------------------------------------------------------------------------------------------- |
| `IMAGE_GEN_PROVIDER` | 아니오 | `google`                         | `google` (Gemini 네이티브 API) 또는 `openai` (OpenAI 호환 `/v1/images/generations`)                     |
| `IMAGE_GEN_API_KEY`  | 아니오 | —                                | Google AI Studio 키 (`google`) 또는 프록시/OpenAI API 키 (`openai`)                                    |
| `IMAGE_GEN_MODEL`    | 아니오 | `gemini-3.1-flash-image-preview` | 이미지 생성 모델 (예: `dall-e-3`, `gemini-nano-banana-2`)                                               |
| `IMAGE_GEN_BASE_URL` | 아니오 | *(공급자별)*                         | Google: `https://generativelanguage.googleapis.com/v1beta`; OpenAI: `https://api.openai.com/v1` |

***

## Email (SMTP) (권장)

`SMTP_HOST`, `SMTP_USER`, `SMTP_PASS`가 모두 설정되면 `email_send` 내장 도구를 자동으로 등록합니다.

| Variable                 | Required | Default              | Description                                                                                                           |
| ------------------------ | -------- | -------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `SMTP_HOST`              | Cond.    | —                    | SMTP 서버 호스트명                                                                                                          |
| `SMTP_PORT`              | No       | `465`                | SMTP 포트                                                                                                               |
| `SMTP_SSL`               | No       | `ssl`                | TLS 모드: `ssl` (포트 465) / `tls` (STARTTLS, 포트 587) / `none` 또는 `""` (평문, 자격증명이 평문으로 전송됨). 다른 값은 평문으로 자동 폴백되지 않고 거부됩니다. |
| `SMTP_USER`              | Cond.    | —                    | SMTP 로그인 사용자명                                                                                                         |
| `SMTP_PASS`              | Cond.    | —                    | SMTP 로그인 비밀번호                                                                                                         |
| `SMTP_FROM`              | No       | *(uses `SMTP_USER`)* | From 헤더에 표시되는 발신자 주소                                                                                                  |
| `SMTP_FROM_NAME`         | No       | —                    | From 헤더에 표시되는 표시 이름                                                                                                   |
| `SMTP_REPLY_TO`          | No       | —                    | Reply-To 주소; 회신이 `SMTP_FROM` 대신 여기로 전송됨                                                                               |
| `SMTP_ALLOWED_DOMAINS`   | No       | —                    | 쉼표로 구분된 도메인 허용 목록 (예: `example.com,corp.io`); 나열된 도메인 외의 수신자를 차단함                                                     |
| `SMTP_ALLOWED_ADDRESSES` | No       | —                    | 쉼표로 구분된 정확한 주소 허용 목록; `SMTP_ALLOWED_DOMAINS`과 함께 적용됨; 모든 수신자를 허용하려면 둘 다 설정하지 않음 (공유 메일박스의 경우 권장하지 않음)                 |

***

## 커넥터

| 변수                             | 필수  | 기본값           | 설명                                                                                                                                                                    |
| ------------------------------ | --- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CONNECTOR_RESPONSE_MAX_CHARS` | 아니오 | `50000`       | 배열이 아닌 JSON / 일반 텍스트 커넥터 응답의 최대 문자 수                                                                                                                                  |
| `CONNECTOR_RESPONSE_MAX_ITEMS` | 아니오 | `10`          | 커넥터 응답이 JSON 배열일 때 유지할 최대 배열 항목 수                                                                                                                                     |
| `CREDENTIAL_ENCRYPTION_KEY`    | 아니오 | *(설정되지 않음)*   | 커넥터 자격증명 blob에 대한 Fernet 암호화 키. 설정되면 `connector_credentials`에 저장된 인증 토큰이 저장 시 암호화됩니다. 설정되지 않으면 자격증명이 일반 텍스트 JSON으로 저장됩니다(하위 호환성). 이 키를 변경하면 기존의 모든 암호화된 자격증명이 무효화됩니다. |
| `CONNECTOR_TOOL_MODE`          | 아니오 | `progressive` | 커넥터 도구가 에이전트에 노출되는 방식. `progressive`: `discover`/`execute` 하위 명령이 있는 단일 `ConnectorMetaTool`(커넥터당 \~30 토큰). `classic`: 작업당 하나의 도구(레거시, 작업당 \~250 토큰).                  |
| `DATABASE_TOOL_MODE`           | 아니오 | `progressive` | 데이터베이스 커넥터 도구가 에이전트에 노출되는 방식. `progressive`: `list_tables`/`discover`/`query` 하위 명령이 있는 단일 `DatabaseMetaTool`. `legacy`: 데이터베이스 커넥터당 작업당 하나의 도구(각 3개 도구).             |
| `MCP_TOOL_MODE`                | 아니오 | `progressive` | MCP 서버 도구가 에이전트에 노출되는 방식. `progressive`: `discover`/`call` 하위 명령이 있는 단일 `MCPServerMetaTool`. `legacy`: MCP 서버 작업당 하나의 도구(원본 개별 도구).                                   |

***

## Platform

| Variable                         | Required | Default                                 | Description                                                                                                                                                                                                                         |
| -------------------------------- | -------- | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DATABASE_URL`                   | No       | `sqlite+aiosqlite:///./data/fim_one.db` | 데이터베이스 연결 문자열. **SQLite** (설정 불필요): `sqlite+aiosqlite:///./data/fim_one.db`. **PostgreSQL** (프로덕션): `postgresql+asyncpg://user:pass@localhost:5432/fim_one`. Docker Compose는 PostgreSQL을 자동으로 설정합니다.                                |
| `JWT_SECRET_KEY`                 | No       | `CHANGE_ME`                             | JWT 토큰 서명용 비밀 키. 플레이스홀더 값 `CHANGE_ME`(또는 기타 레거시 기본값)는 첫 시작 시 안전한 256비트 난수 키를 자동 생성하도록 트리거하며, 이는 `.env`에 다시 기록됩니다. 재시작 및 복제본 간에 토큰 유효성을 유지하려면 프로덕션에서 명시적으로 설정하세요.                                                                    |
| `FIM_BCRYPT_COST`                | No       | `12`                                    | 비밀번호 해싱을 위한 bcrypt 작업 계수(4-31로 제한). 기본값 12는 최신 CPU에서 해시당 약 200ms 소요됩니다. 약한 하드웨어에서는 낮추고, 보안 강화 배포에서는 높이세요.                                                                                                                           |
| `CORS_ORIGINS`                   | No       | —                                       | 기본 localhost 항목 외에 허용되는 추가 CORS 원본의 쉼표 구분 목록. 프론트엔드가 비localhost 도메인에서 실행될 때 필수입니다(예: `https://app.example.com`).                                                                                                                    |
| `UPLOADS_DIR`                    | No       | `./uploads`                             | 업로드된 파일용 디렉토리                                                                                                                                                                                                                       |
| `EXPORT_FONT_DIR`                | No       | *(자동 감지)*                               | PDF 내보내기용 `NotoSansSC-Regular.ttf` / `NotoSansSC-Bold.ttf`를 보유한 디렉토리. `python scripts/fetch_export_fonts.py`로 가져오세요. Docker 이미지는 이미 번들로 포함되어 있습니다. 포함 가능한 TrueType CJK 글꼴이 없으면 PDF 내보내기는 포함되지 않은 CID 글꼴로 폴백되어 간격이 저하되고 굵게 표시가 없습니다. |
| `MAX_UPLOAD_SIZE_MB`             | No       | `50`                                    | 최대 파일 업로드 크기(메가바이트 단위, 백엔드 적용)                                                                                                                                                                                                      |
| `NEXT_PUBLIC_MAX_UPLOAD_SIZE_MB` | No       | `50`                                    | 프론트엔드 UI에 표시되는 최대 파일 업로드 크기. **빌드 시간 변수** — `MAX_UPLOAD_SIZE_MB`와 일치해야 합니다.                                                                                                                                                         |
| `MCP_SERVERS`                    | No       | —                                       | MCP 서버 구성의 JSON 배열(`uv sync --extra mcp` 필요)                                                                                                                                                                                        |
| `ALLOW_STDIO_MCP`                | No       | `false`                                 | stdio MCP 서버 허용. 신뢰할 수 있는 로컬 배포에서만 `true`로 설정하세요                                                                                                                                                                                    |
| `ALLOWED_STDIO_COMMANDS`         | No       | `npx,uvx,node,python,python3,deno,bun`  | stdio MCP 서버에 허용되는 기본 명령의 쉼표 구분 목록. `ALLOW_STDIO_MCP=true`일 때만 유효합니다                                                                                                                                                                |
| `LOG_LEVEL`                      | No       | `INFO`                                  | 로깅 수준: `DEBUG` / `INFO` / `WARNING` / `ERROR` / `CRITICAL`                                                                                                                                                                          |
| `REDIS_URL`                      | No       | —                                       | 크로스 워커 인터럽트 릴레이용 Redis 연결 URL. **`WORKERS>1`일 때 필수** — 없으면 스트림 중 인터럽트/주입 요청이 다른 워커에 도달하여 자동으로 실패할 수 있습니다. Docker Compose에서 자동 구성됩니다.                                                                                                |
| `WORKERS`                        | No       | `1`                                     | Uvicorn 워커 프로세스. `1`은 안전하며 외부 서비스가 필요하지 않습니다. 프로덕션 다중 워커의 경우 PostgreSQL을 사용하세요(SQLite는 단일 쓰기). SQLite는 가벼운 로드 하에서 로컬 개발에 적합합니다. 인증, OAuth 및 파일 작업은 완전히 다중 워커 안전합니다(JWT 기반). Docker Compose는 PostgreSQL과 Redis를 자동으로 구성합니다.          |

<Warning>
  **다중 워커 체크리스트** (`WORKERS>1`):

  * **중지(스트림 중단)** — 항상 작동하며, 추가 구성이 필요하지 않습니다(신호는 동일한 TCP 연결을 통해 이동).
  * **주입(스트림 중 후속)** — **`REDIS_URL` 필수**. Redis 없으면 주입 요청이 실행 중인 실행에 대한 지식이 없는 다른 워커에 도달하여 자동으로 실패할 수 있습니다.
  * **프로덕션**: PostgreSQL(`DATABASE_URL`)을 사용하세요. SQLite의 단일 쓰기 잠금은 동시 쓰기 시 경합을 유발할 수 있습니다.
  * **로컬 개발**: SQLite + 다중 워커는 가벼운 사용에 적합합니다. 주입 기능을 사용하면 `REDIS_URL`을 추가하세요.
</Warning>

## 워크플로우 실행 보관

오래된 워크플로우 실행을 자동으로 정리하는 백그라운드 작업입니다. 워크플로우 설정 UI에서 구성한 워크플로우별 재정의가 이러한 전역 기본값보다 우선합니다.

| 변수                                    | 필수  | 기본값   | 설명                                   |
| ------------------------------------- | --- | ----- | ------------------------------------ |
| `WORKFLOW_RUN_MAX_AGE_DAYS`           | 아니요 | `30`  | 이 일수보다 오래된 워크플로우 실행 삭제               |
| `WORKFLOW_RUN_MAX_PER_WORKFLOW`       | 아니요 | `100` | 워크플로우당 최대 이 개수의 실행 유지(가장 오래된 것부터 삭제) |
| `WORKFLOW_RUN_CLEANUP_INTERVAL_HOURS` | 아니요 | `24`  | 백그라운드 정리 작업 실행 빈도(시간 단위)             |

### 채널 확인 요청 만료

`FeishuGateHook` 또는 Approval Playground와 같은 채널 hook에서 생성된 대기 중인 승인 요청을 오래된 것으로 표시하는 백그라운드 sweeper입니다. 나중에 잊혀진 카드를 클릭해도 이미 해제된 agent 상태가 뒤집히지 않도록 합니다.

| Variable                                      | Required | Default | Description                                 |
| --------------------------------------------- | -------- | ------- | ------------------------------------------- |
| `CHANNEL_CONFIRMATION_TTL_MINUTES`            | No       | `1440`  | 이 시간보다 오래된 대기 중인 확인은 자동으로 만료됩니다 (기본값: 24시간) |
| `CHANNEL_CONFIRMATION_SWEEP_INTERVAL_SECONDS` | No       | `600`   | 만료 sweeper가 실행되는 빈도 (기본값: 10분마다)            |

## OAuth (선택 사항)

공급자에 대해 `CLIENT_ID`와 `CLIENT_SECRET`이 모두 설정되면 로그인 페이지에 해당 OAuth 버튼이 자동으로 표시됩니다.

| 변수                      | 필수       | 기본값                          | 설명                                                                                                                                                                                    |
| ----------------------- | -------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GITHUB_CLIENT_ID`      | 아니오      | —                            | GitHub OAuth App 클라이언트 ID. [github.com/settings/developers](https://github.com/settings/developers) → OAuth Apps에서 생성                                                                 |
| `GITHUB_CLIENT_SECRET`  | 아니오      | —                            | GitHub OAuth App 클라이언트 시크릿                                                                                                                                                            |
| `GOOGLE_CLIENT_ID`      | 아니오      | —                            | Google OAuth 클라이언트 ID. [console.cloud.google.com/apis/credentials](https://console.cloud.google.com/apis/credentials)에서 생성                                                            |
| `GOOGLE_CLIENT_SECRET`  | 아니오      | —                            | Google OAuth 클라이언트 시크릿                                                                                                                                                                |
| `DISCORD_CLIENT_ID`     | 아니오      | —                            | Discord OAuth2 클라이언트 ID. [discord.com/developers](https://discord.com/developers/applications)에서 생성                                                                                   |
| `DISCORD_CLIENT_SECRET` | 아니오      | —                            | Discord OAuth2 클라이언트 시크릿                                                                                                                                                              |
| `FEISHU_APP_ID`         | 아니오      | —                            | Feishu (Lark) App ID. [open.feishu.cn](https://open.feishu.cn/app)에서 생성. `contact:user.email:readonly` 권한 필요                                                                          |
| `FEISHU_APP_SECRET`     | 아니오      | —                            | Feishu (Lark) App Secret                                                                                                                                                              |
| `FRONTEND_URL`          | **프로덕션** | `http://localhost:3000`      | OAuth 완료 후 브라우저가 이동할 위치. 프로덕션에서 설정 필수 (예: `https://yourdomain.com`)                                                                                                                   |
| `API_BASE_URL`          | **프로덕션** | `http://localhost:8000`      | 외부에서 접근 가능한 백엔드 URL, OAuth 콜백 URL 구성에 사용. 프로덕션에서 설정 필수                                                                                                                                |
| `NEXT_PUBLIC_API_URL`   | **프로덕션** | *(자동 감지: `<hostname>:8000`)* | OAuth 리다이렉트를 위한 브라우저 측 API 기본 URL. **이것은 프론트엔드 빌드 타임 변수**입니다 — 로컬 개발의 경우 `frontend/.env.local`에서 설정하거나, 커스텀 프로덕션 배포의 경우 Docker 빌드 인자로 전달하세요. 자동 감지는 표준 리버스 프록시 설정(포트 80/443)에서 작동합니다. |

> **프로덕션** = 로컬에서는 선택 사항(기본값 작동), 하지만 인터넷에 노출된 배포의 경우 **필수**입니다.

### 각 제공자에 등록할 OAuth 콜백 URL

백엔드는 콜백 URL을 다음과 같이 구성합니다: `{API_BASE_URL}/api/auth/oauth/{provider}/callback`

| 제공자     | 등록할 콜백 URL                                               |
| ------- | -------------------------------------------------------- |
| GitHub  | `https://yourdomain.com/api/auth/oauth/github/callback`  |
| Google  | `https://yourdomain.com/api/auth/oauth/google/callback`  |
| Discord | `https://yourdomain.com/api/auth/oauth/discord/callback` |

***

## Cloudflare Tunnel (선택사항)

Cloudflare의 네트워크를 통해 모든 트래픽을 라우팅하여 포트를 직접 노출하지 않습니다. Nginx, SSL 인증서 및 열린 방화벽 규칙의 필요성을 제거합니다. 설정 지침은 [프로덕션 배포](/quickstart#cloudflare-tunnel) 섹션을 참조하세요.

<Warning>
  **중국 본토 사용자**: Cloudflare Free/Pro/Business 플랜은 중국 본토에 PoP가 없습니다. 트래픽이 해외 엣지로 라우팅되어 502 오류가 자주 발생합니다. 중국 네트워크가 있는 Cloudflare Enterprise가 없는 한 주요 사용자가 중국 본토에 있는 경우 이를 사용하지 마세요.
</Warning>

| 변수                        | 필수                  | 기본값 | 설명                                                                                                                                                         |
| ------------------------- | ------------------- | --- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CLOUDFLARE_TUNNEL_TOKEN` | **예** (Tunnel 사용 시) | —   | Cloudflare Zero Trust → Networks → Tunnels → your tunnel → Configure에서 가져온 토큰입니다. `eyJ...`로 시작합니다. `docker-compose.tunnel.yml`의 `cloudflared` 사이드카에 필요합니다. |

***

## 분석 (선택사항)

모든 분석 제공자는 선택사항입니다. 원하는 조합으로 설정하면 모든 활성 제공자가 동시에 로드됩니다. 분석을 완전히 비활성화하려면 모두 비워두세요(로컬 개발에 권장).

| 변수                                 | 필수  | 기본값                                 | 설명                                                                                                               |
| ---------------------------------- | --- | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `NEXT_PUBLIC_GA_MEASUREMENT_ID`    | 아니요 | —                                   | Google Analytics 4 측정 ID (예: `G-XXXXXXXXXX`). [analytics.google.com](https://analytics.google.com)에서 발급받으세요      |
| `NEXT_PUBLIC_UMAMI_SCRIPT_URL`     | 아니요 | —                                   | Umami 분석 스크립트 URL (예: `https://your-umami.com/script.js`). 자체 호스팅, 개인정보 보호 친화적 대안 — [umami.is](https://umami.is) |
| `NEXT_PUBLIC_UMAMI_WEBSITE_ID`     | 아니요 | —                                   | Umami 웹사이트 ID. `NEXT_PUBLIC_UMAMI_SCRIPT_URL`이 설정되어 있을 때 필수                                                      |
| `NEXT_PUBLIC_PLAUSIBLE_DOMAIN`     | 아니요 | —                                   | Plausible 분석 도메인 (예: `yourdomain.com`). 경량, 개인정보 보호 친화적 — [plausible.io](https://plausible.io)                   |
| `NEXT_PUBLIC_PLAUSIBLE_SCRIPT_URL` | 아니요 | `https://plausible.io/js/script.js` | 자체 호스팅 인스턴스용 커스텀 Plausible 스크립트 URL                                                                              |

> 모든 `NEXT_PUBLIC_*` 분석 변수는 **빌드 시간** 변수입니다 — 변경사항을 적용하려면 프론트엔드를 다시 빌드해야 합니다.

## Stripe 결제 (선택사항)

Stripe는 Pro 구독을 지원합니다. 세 변수를 모두 비워두면 결제 기능이 비활성화되며, FIM One의 나머지 기능은 정상 작동합니다. **`STRIPE_SECRET_KEY`와 `STRIPE_WEBHOOK_SECRET`을 함께 설정해야 합니다**. 부분적인 설정은 첫 사용 시 오류를 발생시킵니다.

| 변수                          | 필수  | 기본값                                          | 설명                                                                                                                                                                           |
| --------------------------- | --- | -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `STRIPE_SECRET_KEY`         | 아니요 | —                                            | Stripe API 시크릿 키입니다. `sk_test_` / `sk_live_`(전체 액세스) 또는 `rk_test_` / `rk_live_`(제한된 키)로 시작해야 합니다. Stripe 대시보드 → Developers → API keys에서 발급받으세요. `sk_live_*` 키를 소스에 커밋하지 마세요. |
| `STRIPE_WEBHOOK_SECRET`     | 아니요 | —                                            | Stripe 웹훅 서명 시크릿(`whsec_*`)입니다. Stripe 대시보드 → Developers → Webhooks → Add endpoint에서 웹훅 엔드포인트를 등록할 때 생성됩니다. 인바운드 웹훅 페이로드를 검증하는 데 필요합니다.                                      |
| `STRIPE_BILLING_RETURN_URL` | 아니요 | `http://localhost:3000/settings?tab=billing` | Checkout 또는 Customer Portal 세션 후 Stripe가 사용자를 리다이렉트할 URL입니다. 프로덕션 결제 설정 페이지로 설정하세요(예: `https://your-domain.com/settings?tab=billing`).                                       |
