---
domain: agent
last_rule_review_commit: 99cc06767f82a32a9106f3a483bce2b6aeed5872
last_rule_updated_at: 2026-06-13
---

# agent

## 목적 / 책임

OTO Server에 CLI 기반 runner agent를 등록하고, agent config 파싱, 등록/heartbeat/disconnect, remote job claim, remote pipeline 실행, 실행 결과/로그/artifact 보고, bootstrap 스크립트를 담당한다.
파이프라인 실행 엔진이나 scheduler 등록 정책이 아니라 `oto agent run --config <path>` 실행 흐름과 OTO Server runner 세션 초기화가 이 도메인의 책임이다.

## 포함 경로

- `apps/runner/lib/cli/commands/command_agent.dart` — `agent run --config <path>` CLI 표면과 오류 출력
- `apps/runner/lib/oto/agent/` — agent config, runner, OTO Server 등록/job client, remote run executor, legacy iop Edge compatibility client, generated protobuf 런타임 코드
- `apps/runner/assets/script/shell/oto_agent_bootstrap.sh` — Linux agent 다운로드, server config 생성, background 실행 bootstrap

## 제외 경로

- `apps/runner/lib/cli/cli.dart` — 일반 CLI 출력/초기화 (`cli` 도메인)
- `apps/runner/lib/cli/commands/command_catalog.dart` — command catalog 출력 (`cli` 도메인)
- `apps/runner/lib/cli/commands/command_validate.dart` — pipeline YAML 검증 (`cli`/`core` 도메인)
- `apps/runner/lib/cli/commands/command_scheduler.dart` — scheduler 명령 진입 (`scheduler` 도메인)
- `apps/runner/lib/oto/application.dart` — pipeline build 오케스트레이션 (`core` 도메인)
- `apps/runner/lib/oto/core/build_result.dart` — 실행 결과/step event/artifact 결과 모델 (`core` 도메인)
- `apps/runner/lib/oto/core/output_port.dart` — runner 출력 포트 추상화 (`core` 도메인)
- `apps/runner/lib/cli/runner_output_adapter.dart` — CLI 출력 포트 adapter (`cli` 도메인)
- `apps/runner/lib/oto/pipeline/` — pipeline workflow 실행 (`pipeline` 도메인)
- `apps/runner/lib/oto/commands/` — pipeline에서 호출되는 커맨드 구현체 (`command` 도메인)
- `apps/runner/lib/oto/commands/runner_command_capability_provider.dart` — agent 등록용 command catalog capability provider (`command` 도메인)
- `apps/runner/assets/script/`의 기타 build/package helper — CLI/배포 보조 asset (`cli` 도메인)

## 주요 구성 요소

- `CommandAgent` — `agent` CLI subcommand 파싱, config 로딩, runner 호출, exit code 처리
- `AgentConfig` / `AgentIdentityConfig` / `ServerConnectionConfig` / `EdgeConnectionConfig` / `AgentRuntimeConfig` — agent bootstrap YAML 구조와 필수 필드 검증
- `AgentConfigException` — config 파일/필드/타입 오류 표현
- `AgentRunner` / `DefaultAgentRunner` — OTO Server 등록 workflow, remote job loop, 결과 로그 출력
- `RegistrationException` — OTO Server 등록 거절 또는 연결 실패 표현
- `RegistrationClient` / `AgentSession` / `OtoServerJobSession` — 등록 transport와 세션 수명주기 추상화
- `OtoServerRegistrationClient` — HTTP 기반 runner register, heartbeat, disconnect 요청
- `OtoServerJobClient` — job claim, execution report, log append, artifact report, cancel, status, self-update 요청
- `RemoteRunExecutor` / `RunRequestParser` / `RemoteRunInput` — OTO Server `RunRequest`를 workspace-confined YAML 실행 입력으로 변환하고 `Application.build()` 결과를 보고
- `RunnerCapabilityProvider` / `RunnerCapabilitySnapshot` — 등록 시 runner capability와 command catalog 요약 제공 계약
- `RegistrationResult` — OTO Server/iop response의 accepted/rejected 결과 변환
- `EdgeEndpoint` / `EdgeRegistrationClient` / `_OtoIopClient` — legacy iop Edge compatibility 경로. 기본 runner 경로에서는 `OtoServerRegistrationClient`를 사용
- `apps/runner/lib/oto/agent/oto/*.pb*.dart` — `proto/oto/runner.proto` generated Dart protobuf 코드
- `apps/runner/lib/oto/agent/iop/*.pb*.dart` — legacy `iop/runtime.proto` generated protobuf 코드
- `oto_agent_bootstrap.sh` — agent config 파일 생성, 권한 설정, background 실행 bootstrap

## 유지할 패턴

- `CommandAgent`는 subcommand/argument 파싱과 출력만 담당하고, config 파싱은 `AgentConfig`, 등록 실행은 `AgentRunner`에 위임한다.
- `--config <path>`와 `--config=<path>` 형식을 모두 유지하고, 누락/알 수 없는 인자는 실행 전에 오류 처리한다.
- `AgentConfig`는 YAML root와 `agent`, `server`(또는 legacy `edge`), `runtime` section이 map인지 확인한 뒤 required string을 검증한다.
- agent config의 required field는 빈 문자열을 거부하고, optional `agent.alias`는 누락 시 `null`, 빈 문자열이면 빈 문자열로 보존한다.
- OTO Server URL은 scheme 없는 host도 허용하고, HTTP endpoint 생성 시 기본 `http://`로 해석한다.
- OTO Server 등록 세션은 `openSession()`에서 열고 세션 소유자가 `finally`에서 `AgentSession.close()`를 호출해 heartbeat timer와 HTTP client를 정리한다.
- 기본 agent loop는 job claim 실패를 "대기할 작업 없음"으로 보고 polling을 계속하고, claim된 `RunRequest`는 `RemoteRunExecutor.runOnce()`로 실행한다.
- remote YAML path는 `workspaceRoot` 아래로 confinement를 강제하고, inline YAML이 있으면 path보다 우선한다.
- remote variables는 YAML `property` map 위에 overlay하되, 기존 `property`가 map이 아니면 원본 YAML을 유지해 `Application.build()` 검증이 실패하게 한다.
- `property.artifacts` 선언은 `name`/`path` map list만 허용하고, artifact path도 workspace confinement를 통과해야 한다.
- RegisterResponse/JSON 변환은 `RegistrationResult`에 모아 accepted/rejected와 runner id/alias 추출을 한 곳에서 처리한다.
- generated protobuf 파일은 직접 수정하지 않고 원본 proto와 생성 절차를 확인해 재생성한다.
- bootstrap 스크립트는 `--server-url`을 기본 인자로 사용하고 legacy `--edge-url`도 server URL로 받는다.
- bootstrap 스크립트는 `--release-base-url`에 https만 허용하고, 생성한 config 파일은 `chmod 600`을 유지한다.
- legacy iop Edge 경로는 `edge_registration_client.dart` 안에 격리하고, 기본 production runner 경로에서 직접 import하지 않는다.
- agent 변경 후 `dart analyze`와 agent 관련 테스트(`apps/runner/test/oto_agent_*`, `apps/runner/test/oto_server_connection_smoke_test.dart`, 필요 시 `apps/runner/test/oto_iop_connection_smoke_test.dart`)를 확인한다.

## 다른 도메인과의 경계

- **cli**: `apps/runner/bin/main.dart` 등록, 일반 출력/스타일, `CliRunnerOutputPort` adapter는 cli 도메인이다. `CommandAgent` 내부의 agent subcommand 정책부터는 agent 도메인이다.
- **core/pipeline/command**: agent 등록은 pipeline build 실행과 별개다. remote job 실행은 `Application.build()` 진입점까지만 호출하고, `Pipeline.pipelineInitialize()`나 `Command.byType()`을 직접 호출하지 않는다.
- **core**: remote run 실행 결과를 담는 `BuildResult`, `StepEvent`, `BuildArtifact`, `RunnerOutputPort`는 core 도메인이다. agent 도메인은 이를 서버 보고 payload로 변환해 전송한다.
- **command**: runner capability의 command catalog 계산은 command 도메인의 `CommandCatalogRunnerCapabilityProvider`가 담당한다. agent 도메인은 provider interface만 소비한다.
- **scheduler**: scheduler는 YAML 파이프라인을 cron/interval로 실행한다. agent bootstrap의 background 실행과 scheduler 등록/로그 정책을 섞지 않는다.
- **framework**: `http`, `proto_socket`, `protobuf`, `fixnum` dependency 선언과 `proto/oto/runner.proto` 생성 절차는 framework 도메인에서 관리하고, OTO Server/iop protocol 사용 방식은 agent 도메인에서 관리한다.
- **sample**: agent config YAML은 pipeline sample YAML이 아니다. `apps/runner/assets/yaml/sample/**`에 agent bootstrap config를 섞지 않는다.

## 금지 사항

- agent 도메인에서 pipeline workflow나 command catalog를 직접 해석하지 않는다. remote job 실행은 `Application.build()` 진입점까지만 호출한다.
- enrollment token, generated config, server/Edge 응답 중 민감 정보가 로그에 노출되도록 하지 않는다.
- generated protobuf 파일을 수동 편집하지 않는다.
- remote run의 YAML path나 artifact path가 `workspaceRoot` 밖으로 빠져나가도록 허용하지 않는다.
- bootstrap 스크립트에서 사용자가 지정한 config/log/workspace 경로 외 임의의 프로젝트 파일을 수정하지 않는다.
- agent background 실행 정책을 scheduler 등록/해제 로직에 섞지 않는다.
