본문으로 건너뛰기
가이드

Agent Gateway 켜기

로컬 service token을 채워 Agent Edge·Gateway를 실행하고 두 runtime 경계를 검증합니다.

Agent Gateway 켜기

이 문서는 비공개 호스트 환경에 이미 접근 권한이 있는 Nexia 유지관리자를 위한 참고 자료입니다. Core는 외부 개발자에게 배포하지 않습니다. 아래 호스트 명령은 공개 CLI·클라우드 샌드박스의 선행 조건이 아닙니다. 외부 개발자는 빠른 시작을 따라주세요.

로컬 Agent 동작은 1–3단계로 시작하고 채팅 전에 4단계에서 provider와 model을 설정하세요. Health는 runtime 경계, 인증된 대화 완료는 model과 stream 경로를 확인합니다. 운영 배포 절은 Gateway를 배포하는 운영자를 위한 내용입니다.

만들 결과물

로컬에서 실행 중인 Agent Edge와 Gateway입니다. Edge는 browser의 일회용 direct-SSE ticket을 처리하고 응답을 stream합니다. Gateway는 Shell의 Agent chat을 실행하는 Python LangGraph sidecar로, 업무 데이터는 위임 토큰으로 Laravel 테넌트 API를 호출해 다룹니다. 대화 복구용 LangGraph 체크포인트는 별도의 PostgreSQL 연결에 저장합니다.

일반 App·Core·SDK 작업에는 필요하지 않습니다. Agent 동작을 실행하거나 Gateway 자체를 수정할 때만 켭니다.

준비 사항

  • Nexia 내부 설치 절차로 준비한 접근 허가된 비공개 Core 체크아웃의 task doctor Summary에서 실패가 0인 상태
  • Core 저장소 루트에 있는 터미널

서명용 RS256 keypair는 이미 있습니다. task setup이 nexia-agent:generate-keys를 실행해 storage/app/agent-keys/에 private.pem과 public.pem을 생성해 뒀습니다. 다시 만들 필요 없습니다.

1. Service token 채우기

이미 작동하는 토큰은 유지하세요. 로컬 값이 비어 있을 때만 생성합니다.

Edge adapter와 Gateway가 Laravel의 /internal/agent/* endpoint에 자신을 증명하는 공유 secret 하나가 로컬에서 유일하게 직접 채우는 값입니다. .env의 AGENT_SERVICE_TOKEN은 기본이 비어 있고, 비어 있으면 Laravel이 요청을 전부 거부합니다(fail closed).

코드 예시
Shell
token="$(openssl rand -hex 32)"
sed -i '' "s/^AGENT_SERVICE_TOKEN=.*/AGENT_SERVICE_TOKEN=${token}/" .env
awk -F= '/^AGENT_SERVICE_TOKEN=/ { print length($2) }' .env

출력은 64여야 합니다. 토큰 값은 .env에만 남습니다. .env는 Octane watch 대상이라 Laravel 쪽은 저장 즉시 다시 읽습니다.

2. Agent 모드로 실행

코드 예시
Shell
task dev:up:agent

core 모드 위에 agent-gateway, 추적되는 로컬 agent-gateway-edge, 로컬 agent-analysis controller를 추가로 올립니다. 방금 바꾼 .env 값은 Compose가 Agent runtime 경계에 주입하므로 이 명령이 곧 반영 절차입니다. Direct SSE가 로컬 기본값이며 별도의 ignored helper process는 필요 없습니다.

Agent 답변 token은 Reverb가 아니라 이 direct-SSE 경로를 사용합니다. .env가 Reverb broadcaster를 선택하거나 browser Reverb key를 제공하면 같은 명령이 reverb도 함께 실행합니다. WebSocket channel은 agent.task.changed cache 무효화와 그 밖의 Shell realtime event를 더 빨리 반영하며, realtime transport가 없을 때는 Agent task polling이 fallback으로 동작합니다.

3. 로컬 두 경계 검증

로컬 Edge adapter에는 process health endpoint가 있습니다.

코드 예시
Shell
curl -fsS http://localhost:8787/_local/health

{"status":"ok"}는 추적되는 adapter가 요청을 받고 있음을 증명합니다. 이 응답만으로 ticket exchange나 browser stream까지 증명되지는 않습니다.

Gateway는 부팅할 때 Laravel에 tool manifest를 한 번 제한된 시도로 요청하고, Laravel이 준비되지 않았다면 백그라운드에서 계속 복구합니다. 성공하기 전까지 /agent/health는 503 degraded를 반환하므로 잠시 뒤에 확인합니다.

코드 예시
Shell
curl -s http://localhost:8100/agent/health

응답 JSON의 "status": "ok"와 0이 아닌 tool_count가 성공 증거입니다. 포트는 .env의 AGENT_GATEWAY_PORT(기본 8100)입니다.

계속 degraded라면 token이 원인일 가능성이 큽니다.

코드 예시
Shell
task agent:logs

Laravel이 503(token 미설정) 또는 401(양쪽 값 불일치)로 거부한 기록이 보이면 1단계로 돌아갑니다.

4. 채팅 모델 설정

채팅 provider·model·API key는 환경 변수가 아니라 중앙 카탈로그 데이터입니다. Core host의 /admin/login에서 Central Admin에 로그인한 뒤 Agent 그룹에서 설정합니다. 표준 로컬 주소는 http://localhost:8080/admin/login이며, 별도 worktree가 다른 포트를 배정받았다면 host와 port만 현재 Core 주소로 바꿉니다. Laravel이 준비한 turn마다 해석된 {provider, model_id, api_key} 후보를 Gateway로 보내므로 Gateway process나 .env에는 채팅 모델 key를 넣지 않습니다.

설정할 것위치Core host 기준 직접 경로
Provider API key중앙 Admin → Agent → Provider Keys/admin/agent-provider-keys
모델 목록중앙 Admin → Agent → Agent Models/admin/agent-models
Primary 등급별 모델 배정중앙 Admin → Agent → Agent Grades/admin/agent-grades
Router·Worker 모델 배정중앙 Admin → Agent → Agent Roles/admin/agent-role-models

4-1. Provider별 공용 key 설정

Agent → Provider Keys에는 초기 데이터가 provider별로 생성되어 있습니다. 사용할 provider 행을 열어 API key와 필요한 경우 Base URL을 입력하고 노출을 켭니다. API key는 각 provider의 관리 console에서 발급받은 값을 사용합니다. 기존 행을 다시 편집할 때 API key 입력란을 비워 두면 저장된 key가 유지됩니다.

Central Admin의 제공자 키 목록에서 provider별 Base URL과 노출 상태를 확인하는 화면.

ProviderAPI keyBase URL
Anthropic필수비움
OpenAI필수비움
Groq필수비움
Gemini필수비움
Z.ai필수https://api.z.ai/api/paas/v4
Hugging Face필수https://router.huggingface.co/v1
Ollama비움Gateway container에서 접근 가능한 Ollama URL. 로컬 기본값은 http://host.docker.internal:11434

Z.ai, Hugging Face, Ollama는 Base URL까지 있어야 사용할 수 있습니다. 그 밖의 provider는 Base URL을 입력해도 Gateway의 해당 adapter가 사용하지 않습니다.

4-2. Provider별 model 설정

다음으로 Agent → Agent Models에서 사용할 model 행을 편집하거나 새로 만듭니다. Provider는 앞에서 key를 설정한 provider와 같아야 하고, Model ID에는 표시용 이름이 아니라 provider API에 전달할 실제 ID를 입력합니다. 현재 환경의 모델 목록에서 시작하고 해당 ID를 제공자 계정에서 사용할 수 있는지 확인하세요.

Central Admin의 에이전트 모델 목록에서 provider, 실제 모델 ID, 등급, 사용 중 모델, 노출 상태와 순서를 확인하는 화면.

각 model에서 노출을 켜고, provider가 지원하는 범위 안에서 최대 출력 token과 context window를 설정합니다. 같은 grade에 model이 여러 개면 정렬 순서가 작은 model부터 시도합니다. 목록의 사용 중 표시는 플랫폼 공용 key를 기준으로 각 grade에서 가장 먼저 선택될 model입니다.

새 chat은 플랫폼 model catalog에서 사용 가능한 grade를 해석해 시작합니다. 실제 chat에 model이 나타나려면 Provider Keys의 해당 provider와 Agent Models의 model이 모두 노출 상태여야 하며, Ollama를 제외하면 유효한 API key도 저장되어 있어야 합니다.

테넌트의 Agent 채팅에서 사용 가능한 등급을 선택하고 짧은 메시지를 보내세요. 답변이 완료되어야 제공자 설정과 브라우저 스트림까지 연결된 것입니다. 모델이 보이지 않으면 제공자·모델의 노출 상태와 제공자 키를 확인하세요.

운영 배포

Loopback Edge adapter는 로컬 개발 인프라입니다. 운영은 services/agent-gateway-edge/wrangler.jsonc가 선언한 Worker·Container를 사용합니다. 해당 디렉터리에서 배포 전 Cloudflare secret을 등록합니다.

코드 예시
Shell
pnpm install --frozen-lockfile
pnpm exec wrangler secret put AGENT_EDGE_TOKEN
pnpm exec wrangler secret put AGENT_SERVICE_TOKEN
pnpm exec wrangler secret put AGENT_CHECKPOINT_DSN_TEMPLATE
# Hosted 화면 검색 embedding을 쓸 때만:
pnpm exec wrangler secret put AGENT_SCREEN_SEARCH_EMBEDDING_API_KEY
pnpm run typecheck
pnpm run test
pnpm exec wrangler deploy --dry-run
pnpm exec wrangler deploy

Laravel Cloud는 다음 대응 인프라 값을 소유합니다.

AGENT_SERVICE_TOKEN=<Cloudflare와 같은 값>
AGENT_GATEWAY_URL=https://<worker-host>
AGENT_EDGE_TOKEN=<Cloudflare와 같은 값>
AGENT_PUBLIC_STREAM_URL=https://<worker-host>/browser/agent/stream
AGENT_JWT_PRIVATE_KEY_BASE64=<Laravel signing key>
AGENT_JWT_PUBLIC_KEY_BASE64=<matching public key>

AGENT_EDGE_TOKEN은 Laravel의 protected Worker /agent/* 요청을 인증하고, AGENT_SERVICE_TOKEN은 Worker·Gateway의 Laravel /internal/agent/* 요청을 인증합니다. Browser는 불투명한 ticket만 받습니다. 두 공유 secret이나 delegation JWT를 browser에 보내지 마세요. Public stream URL은 위와 같은 정확한 path를 가진 절대 HTTPS URL이어야 하며 credential·query·fragment·redirect가 없어야 합니다.

wrangler.jsonc가 canonical screen-search provider binding을 소유합니다. 선택 base URL과 API key도 같은 AGENT_SCREEN_SEARCH_EMBEDDING_* 계약을 사용하며, Worker는 이 이름만 Container로 전달합니다.

배포 후 Edge token으로 인증한 /agent/health 요청은 protected Worker-to-Container 경로를 증명합니다. Ticket exchange와 direct SSE는 실제 인증된 browser turn으로 따로 확인해야 합니다.

선택적 화면 검색 재정렬

화면 검색 embedding은 별도의 Gateway 인프라이며 채팅 모델을 선택하지 않습니다. 기본 none 또는 불완전한 선택 설정은 화면 검색만 lexical 순서로 돌리고 chat은 계속 실행합니다. 알 수 없는 provider나 안전하지 않은 hosted URL은 배포 설정 오류이며 Gateway startup을 중단합니다.

AGENT_SCREEN_SEARCH_EMBEDDING_PROVIDER=none
AGENT_SCREEN_SEARCH_EMBEDDING_BASE_URL=
AGENT_SCREEN_SEARCH_EMBEDDING_API_KEY=

none이면 Laravel이 권한 필터링한 lexical 순서를 그대로 사용합니다. ollama는 query와 화면 label을 배포가 소유한 endpoint 안에서 처리합니다. gemini와 zai는 화면 검색 텍스트를 선택한 hosted provider로 보내며 AGENT_SCREEN_SEARCH_EMBEDDING_API_KEY가 필요합니다. Model identifier는 코드가 소유하므로 instance마다 호환되지 않는 vector space를 조용히 선택할 수 없습니다. Hosted endpoint override는 userinfo, query, fragment, 공백이 없는 절대 HTTPS URL이어야 합니다. 잘못된 override는 Gateway가 credential이나 검색 text를 보내기 전에 startup에서 거부됩니다.

/agent/health는 endpoint나 credential을 노출하지 않고 screen_search_embedding.provider, model, profile_fingerprint, readiness, missing_configuration을 보고합니다. readiness는 설정 모양만 증명하며 provider 연결 가능성을 뜻하지 않습니다. 요청 중 provider가 실패하면 lexical 순서를 유지하고 rate-limit된 provider·실패 분류만 기록합니다. Query와 provider 응답 본문은 기록하지 않습니다. 화면 검색 접두 이름을 붙인 세 환경변수만 허용하며, 이전의 공통·provider별 이름은 무시합니다.

Gateway 자체를 수정한다면

목적명령
로그 추적task agent:logs
서비스 재시작task agent:restart
container shelltask agent:shell
uv workspace 설치task agent:sync
pytest 실행task agent:test

일반 작업으로 돌아갈 때는 task dev:up:core가 두 Agent 서비스를 모두 정지합니다.

검증

확인통과 기준
Token 설정비어 있지 않은 동일한 값이 Laravel·Edge·Gateway에 전달됨. 위에서 새로 생성한 값은 64자
Container 실행task status에 agent-gateway-edge, agent-gateway, agent-analysis 표시
로컬 Edge 정상:8787의 /_local/health가 {"status":"ok"} 반환
Gateway 정상/agent/health가 "status": "ok" 반환
선택적 재정렬 설정/agent/health의 screen_search_embedding.readiness가 disabled, ready, misconfigured 중 하나

흔한 실수

Token 없이 task dev:up:agent 실행. 로컬 Edge adapter는 healthy 상태가 되지 못하고, Gateway는 manifest를 받지 못해 /agent/health가 503 degraded에 머뭅니다. Laravel의 EnsureServiceToken은 미설정 배포를 조용히 통과시키지 않습니다.

채팅 모델 API key를 .env에서 찾기. AGENT_SCREEN_SEARCH_EMBEDDING_API_KEY는 선택적 화면 검색 재정렬 전용입니다. 채팅 모델 key는 중앙 Admin → Agent → Provider Keys의 카탈로그 데이터입니다.

Keypair 재생성으로 문제 해결 시도. nexia-agent:generate-keys는 기존 키가 있으면 중단합니다. --force는 회전 절차(신규 배포 → 코드에 고정된 300초 토큰 유효 기간 만료 대기 → 구키 제거)를 알고 쓰는 옵션입니다.

사용 불가 배너만 보고 원인 단정. service_unavailable과 not_configured는 같은 배너를 표시합니다. 화면의 참조 코드와 task agent:logs로 실제 오류를 확인하세요. not_configured라면 Central Admin에서 제공자 키, 필요한 Base URL, 모델 설정을 점검합니다. Health는 채팅 모델 카탈로그를 검증하지 않아 ok일 수 있습니다. service_unavailable이라면 런타임 로그와 각 경계의 health를 확인합니다.

첫 503을 실패로 판단. 부팅 직후에는 manifest self-heal이 진행 중일 수 있습니다. 잠시 뒤에도 degraded가 유지될 때 token과 로그를 확인합니다.

다음 단계

  • 환경변수 — Agent·Edge·Gateway·선택 서비스의 모든 값을 owner별로 조회합니다.
  • Nexia 시스템 개요 — Gateway가 위임된 API 호출로 Core와 만나는 구조를 봅니다.
  • HTTP 미들웨어 — service-token guard가 App Route 계약이 아닌 이유를 확인합니다.
  • 설정의 소유권 — 어떤 값이 env이고 어떤 값이 카탈로그인지 판단 기준을 봅니다.
원본 위치: docs/developers/content/ko/operations/enable-agent-gateway.md