SSD Nodes Learn Hosting plans →
가이드 Matt Connor작성자 Matt Connor · 업데이트됨 2026-08-21

Deer Workflow VPS 셀프 호스팅 및 systemd 설정 가이드

Deer Workflow를 Ubuntu VPS에 설치하고 Bun 환경에서 에이전트 그래프를 헤드리스로 실행하는 방법을 설명합니다. systemd 서비스 등록부터 PATH 설정, 의존성 버전 고정 및 안정적인 로그 기록을 위한 실무적인 구성 요소를 상세히 다룹니다.

구축할 시스템

Deer Workflow는 에이전트 그래프를 위한 코드 기반 런타임입니다. 제어 흐름은 검토 가능한 TypeScript 파일에 존재하며, 코딩 에이전트는 판단이 필요한 부분만 수행합니다. 이 가이드에서는 Ubuntu VPS 한 대에 이를 설치하고, systemd 하에서 예제 그래프를 헤드리스(headless) 방식으로 실행하며, 새벽 3시에 실행이 실패했을 때 검색할 수 있도록 기계 판독 가능한 이벤트 스트림을 로그 파일에 기록합니다.

구성 요소는 간단합니다. Bun이 CLI를 실행합니다. Codex나 Claude Code와 같은 코딩 에이전트 CLI 하나가 모델 작업을 수행합니다. 고정된 npm 패키지 하나가 런타임을 유지합니다. TypeScript 파일 하나에 그래프가 담깁니다. systemd 서비스와 타이머가 이를 일정에 맞춰 실행합니다. 이 가이드의 대부분은 실제로 문제가 발생하기 쉬운 부분들을 다룹니다. systemd 유닛 내부의 PATH 설정, 로그인 셸이 없는 세션에서의 에이전트 자격 증명, 그리고 2026년 7월에 처음 배포된 의존성 패키지의 버전 고정 등이 이에 해당합니다.

비주얼 빌더, 코드, 또는 에이전트 프롬프팅

모델을 사용하여 작업을 자동화하는 셀프 호스팅 사용자는 세 가지 방식 중 하나를 선택하며, 각 방식은 서로 다른 이유로 실패합니다.

비주얼 빌더는 캔버스, 노드 라이브러리, 그리고 비프로그래머도 열 수 있는 사용자 인터페이스를 제공합니다. 이는 확실한 장점이며, 이 분야는 이미 셀프 호스팅 n8n 대안에 대한 전체 조사가 존재할 정도로 경쟁이 치열합니다. 단점은 로직이 UI에 의해 작성된 JSON 문서 형태로 남는다는 것입니다. 해당 문서의 diff는 매우 복잡하므로, 변경 사항을 검토하려면 패치를 읽는 대신 캔버스를 직접 열어야 합니다.

에이전트를 직접 프롬프팅하는 것이 두 번째 방식입니다. 전체 작업을 문단으로 설명하면 모델이 순서, 재시도, 종료 시점을 결정합니다. 이 방식은 모델이 다른 결정을 내리기 전까지는 잘 작동합니다. 아티팩트가 존재하지 않으므로 diff도 없습니다. 계획은 대화 속에 존재하며, 대화가 끝나면 계획도 사라집니다.

코드를 통한 오케스트레이션이 세 번째 방식입니다. 단계의 순서, 팬아웃(fan-out), 재시도, 오류 처리는 git에 저장된 일반적인 TypeScript 코드입니다. 모델은 판단이 필요한 지점에서만 호출됩니다. 단점은 누군가가 해당 코드를 작성하고 유지보수해야 하며, TypeScript를 작성하지 못하는 동료는 이를 수정할 수 없다는 것입니다.

그래프 런타임의 이점과 비용

  • 검토 가능한 제어 흐름. 그래프는 파일 형태입니다. 재시도 정책을 변경하면 상자 위치가 바뀌는 것이 아니라, 풀 리퀘스트에서 3줄이 변경된 것으로 나타납니다.
  • 버전 관리되는 장애 처리. 4단계에서 실패가 발생할 때 어떤 일이 일어나는지 기록되고, 테스트되며, 나머지 인프라와 함께 태그가 지정됩니다.
  • 교체 가능한 에이전트. 런타임은 Codex, Claude Code, Pi용 어댑터를 제공합니다. 어떤 모델이 단계를 실행할지 바꾸는 것은 import 문 하나로 가능합니다.
  • 관찰 가능한 실행. 단계와 이벤트는 구조화된 데이터로 런타임에서 출력되므로, 헤드리스 실행 시에도 쿼리 가능한 기록이 남습니다.

모델이 실행되는 루프를 설계하는 일반적인 관행을 루프 엔지니어링이라고 하며, 그래프 런타임은 이를 구현하는 구체적인 방법 중 하나입니다. 비용은 설정 과정에서 발생합니다. 런타임을 설치하고, 에이전트 CLI를 인증해야 하며, 비프로그래머를 위한 인터페이스가 없고, 지속적인 관찰이 필요한 초기 단계의 의존성이라는 점이 그 예입니다.

프로젝트가 초기 단계이므로 버전을 고정하십시오

Deer Workflow는 MIT 라이선스를 따르는 신규 프로젝트입니다. 2026년 8월 19일 기준으로 저장소에는 main에 47개의 커밋이 있습니다. npm에는 2026년 7월 26일에 0.0.1과 0.1.0, 2026년 7월 27일에 0.2.0 등 총 3개의 버전이 게시되어 있습니다. 각 버전에는 git 태그가 생성되어 있으며, 변경 사항은 changelog에서 확인할 수 있습니다. 해당 프로젝트의 Unreleased 섹션에서는 이미 deer-workflow agent 명령어가 제거되었으므로, main와 최신 게시 버전에서는 더 이상 동일한 CLI를 제공하지 않습니다.

그렇다고 해서 프로젝트 사용을 피할 이유는 없습니다. 오히려 특정 버전을 정확히 설치하고 자신이 어떤 버전을 설치했는지 파악하는 것이 중요합니다.

  • 버전 범위를 지정하지 말고 정확한 버전을 설치하십시오.
  • 그래프가 저장된 동일한 저장소에 해당 버전을 기록하십시오.
  • 업그레이드 후에는 타이머가 자동으로 실행되기 전에 수동으로 그래프를 한 번 실행해 보십시오.

Bun 및 에이전트 런타임 설치

아래의 모든 작업은 sudo 권한을 가진 일반 사용자로 수행합니다. root 사용자로 실행하지 마십시오. 에이전트 CLI는 로그인한 사용자의 홈 디렉터리에 자격 증명을 저장하며, 이후 systemd 유닛이 해당 자격 증명을 찾으려면 동일한 사용자로 실행되어야 합니다.

sudo apt update
sudo apt install -y curl unzip jq git nodejs npm
curl -fsSL https://bun.com/install | bash

Bun 설치 프로그램은 zip 아카이브를 압축 해제하므로 unzip이 먼저 설치되어 있어야 합니다. 설치 프로그램은 PATH 라인을 셸 프로필에 추가합니다. 현재 셸은 이미 해당 파일을 읽은 상태이므로, 새 셸을 열거나 ~/.bashrc에 다음 두 줄을 직접 추가한 뒤 다시 로드하십시오.

export BUN_INSTALL="$HOME/.bun"
export PATH="$BUN_INSTALL/bin:$HOME/.npm-global/bin:$PATH"
bun --version

위 명령은 버전 번호를 출력합니다. bun: command not found가 나타난다면 설치가 실패한 것이 아니라 현재 셸에 PATH 라인이 누락된 것입니다. 무언가를 재설치하기 전에 ls ~/.bun/bin을 실행하십시오.

이제 에이전트 런타임을 설치합니다. Codex CLI가 기본값이며 npm을 통해 설치됩니다. 전역 설치 시 root 권한이 필요하지 않도록 사용자 수준의 npm prefix를 설정하십시오.

npm config set prefix "$HOME/.npm-global"
npm install -g @openai/codex
command -v codex
codex

command -v codex$HOME/.npm-global/bin 아래의 경로를 출력해야 합니다. codex을 단독으로 실행하면 CLI가 열리며, 여기서 ChatGPT 계정으로 로그인합니다. 화면을 볼 수 있는 지금 한 번 수행하십시오.

Claude Code는 대안 런타임으로 작동하며 별도의 설치 프로그램을 사용합니다.

curl -fsSL https://claude.ai/install.sh | bash
claude --version

정상적으로 설치되면 2.1.211 (Claude Code)과 같은 버전이 출력됩니다. 로그인을 위해 claude을 한 번 실행하십시오. 이는 호스팅하는 다른 에이전트와 동일한 유형의 프로세스이며 파일에 대한 동일한 접근 권한을 가집니다. 따라서 VPS에서 코딩 에이전트 실행하기의 계정 및 보안 강화 관련 주의 사항이 그대로 적용됩니다.

Deer Workflow 설치 및 특정 버전 고정

bun install --global @deerwork-ai/deer-workflow@0.2.0
command -v deer-workflow

command -v는 절대 경로를 출력하며, 일반적으로 /home/<your user>/.bun/bin/deer-workflow입니다. 이 경로를 어딘가에 복사해 두십시오. systemd unit은 파일의 전체 경로를 사용해야 합니다.

설치 명령에 버전을 명시하십시오. @0.2.0을 생략하면 실행 시점의 최신 버전이 설치됩니다. 47개의 커밋이 있는 프로젝트에서는 관리자가 모르는 사이에 타이머에 의해 CLI가 변경될 수 있습니다.

그래프를 git 저장소에 저장하기

mkdir -p ~/workflows/logs
cd ~/workflows
git init

Codex는 자신이 git 저장소 내부에서 실행 중인지 확인합니다. 이것이 바로 저장소를 제공할 수 없는 경우를 위해 CodexAgentConfigskipGitRepositoryCheck 옵션을 포함하는 이유입니다. 직접 운영하는 VPS에서는 저장소를 제공할 수 있으며, 반드시 그렇게 해야 합니다. 그래프는 코드이며, 오케스트레이션을 코드로 작성한다는 논리는 코드가 버전 관리 시스템 하에 있지 않으면 성립하지 않기 때문입니다. systemd는 logs 디렉터리를 자동으로 생성하지 않으므로 지금 직접 생성하십시오.

워크플로 작성

워크플로는 일반적인 TypeScript 모듈입니다. 이 모듈은 이름, 설명, 순차적인 단계 목록을 담은 객체인 meta를 내보내며, 핸들러를 default 또는 명명된 run 내보내기로 제공합니다. 핸들러 내부에서는 패키지에서 제공하는 헬퍼 함수를 호출합니다. phase()은 현재 실행 단계를 표시하고, log()는 진행 상황을 기록하며, agent()은 코딩 에이전트에 프롬프트를 전송합니다. parallel()은 여러 작업을 동시에 실행하며, pipeline()는 항목 목록을 여러 단계에 걸쳐 처리합니다.

이 파일을 ~/workflows/log-triage.ts으로 저장하십시오.

import { agent, log, parallel, phase } from "@deerwork-ai/deer-workflow";

export const meta = {
  name: "log-triage",
  description: "Groups recent service errors and writes one short report.",
  phases: [{ title: "Collect" }, { title: "Classify" }, { title: "Report" }],
  exampleArgs: { service: "nginx", hours: 24 },
};

export default async function workflow(args: { service: string; hours: number }) {
  if (!args?.service) throw new Error("input needs a service name");

  phase("Collect");
  log(`Reading ${args.hours}h of logs for ${args.service}`);
  const found = await agent<{ patterns: string[] }>(
    `Read the last ${args.hours} hours of journalctl -u ${args.service} and list the distinct error patterns.`,
    {
      sandbox: "read-only",
      schema: {
        type: "object",
        properties: { patterns: { type: "array", items: { type: "string" } } },
        required: ["patterns"],
        additionalProperties: false,
      },
    },
  );

  phase("Classify");
  log(`Classifying ${found.patterns.length} patterns`);
  const notes = await parallel(
    found.patterns.map((pattern) => () =>
      agent(`Explain this error and its most likely cause: ${pattern}`, { sandbox: "read-only" }),
    ),
  );

  phase("Report");
  return agent(`Write a short operations report from these notes: ${JSON.stringify(notes.filter(Boolean))}`);
}

해당 파일에서 다음 네 가지 세부 사항이 중요합니다.

  • agent() 호출 시 schema를 사용하면 구조화된 출력을 요청하며, 호출 결과로 파싱된 객체가 반환됩니다. found.patterns은 그래프의 나머지 부분이 순회할 수 있는 실제 배열입니다. 스키마가 없으면 agent()은 문자열을 반환하므로 일반 텍스트를 직접 파싱해야 합니다.
  • sandbox은 해당 단계에서 접근 가능한 범위를 결정합니다. read-only는 쓰기를 차단하고, workspace-write은 보호된 쓰기를 허용하며, danger-full-access은 보호 기능을 제거합니다. 이는 호출 단위로 설정되므로, 그래프는 넓은 범위의 데이터를 읽으면서 특정 위치에만 쓰기를 수행할 수 있습니다.
  • parallel()는 Promise가 아닌 함수를 인자로 받습니다. map((pattern) => () => agent(...))은 thunk 목록을 생성하며, 런타임이 각 작업의 시작 시점을 결정합니다. agent(...)를 직접 전달하면 목록이 생성되는 즉시 모든 호출이 시작됩니다.
  • parallel() 내부에서 실패한 작업은 null이 되며, 부분적인 완료가 설계상 허용되므로 실행은 계속됩니다. 따라서 notes.filter(Boolean)은 단순한 장식이 아닙니다. 이를 생략하면 실패한 분기의 결과로 null이라는 텍스트가 다음 단계의 프롬프트에 포함됩니다.

기본 agent() 헬퍼는 기본 런타임인 Codex를 사용합니다. Claude Code로 단계를 전송하려면 에이전트 클래스를 임포트하여 직접 호출하십시오.

import { ClaudeAgent } from "@deerwork-ai/deer-workflow";

const claude = new ClaudeAgent({ sandbox: "read-only" });
const summary = await claude.run<string>("Summarise ./report.md in five lines.");

이것이 실제 환경에서 교체 가능한 에이전트가 작동하는 방식입니다. 임포트 문과 생성자 하나만 변경하면 되며, 그래프 구조는 그대로 유지됩니다. CLI의 --agent codex|claude|pi 플래그는 설명을 바탕으로 워크플로 파일을 생성하는 deer-workflow create의 기능입니다. 이 플래그는 deer-workflow run가 사용하는 런타임을 변경하지 않습니다.

먼저 수동으로 한 번 실행한 뒤 헤드리스 모드로 전환하기

cd ~/workflows
deer-workflow run ./log-triage.ts --input '{"service":"nginx","hours":24}'

대화형 모드에서는 터미널 인터페이스가 제공됩니다. 한쪽에는 meta의 단계가 표시되고, 다른 쪽에는 실시간 로그가 나타납니다. 자동화를 진행하기 전에 이 방식으로 전체 실행 과정을 한 번 확인하십시오. 에이전트가 로그인되지 않았거나 입력값이 핸들러 시그니처와 일치하지 않는 경우, 다음 주에 로그 파일을 뒤지는 대신 몇 초 안에 문제를 파악할 수 있습니다.

자동화를 위해서는 입력값을 파일로 옮기십시오. ~/workflows/input.json를 저장하십시오:

{ "service": "nginx", "hours": 24 }
deer-workflow run ./log-triage.ts --input-file ./input.json --print >> logs/run.jsonl

--print(단축형 -p)를 사용하면 인터페이스가 꺼지고 이벤트 스트림이 stdout으로 출력되며, 한 줄에 하나의 JSON 객체가 기록됩니다. 이 모드에서는 stdout으로 다른 내용이 출력되지 않으므로, 결과를 바로 .jsonl 파일에 추가하면 모든 줄을 파싱할 수 있는 파일이 생성됩니다.

이벤트 스트림과 새벽 3시에 grep해야 할 대상

모든 라인에는 type, sequence, timestamp, workflowId, depthscriptPath이 포함됩니다. 유형은 workflow:start, workflow:meta, workflow:end, workflow:error, workflow:phase:start, workflow:phase:endlog입니다. 단계(Phase) 이벤트에는 phase이 포함되고, 종료(end) 이벤트에는 durationMs가 포함되며, log 이벤트에는 message가 포함됩니다. 또한 workflow:error 이벤트에는 error과 함께 name, message 및 일반적으로 stack가 포함됩니다.

이 정도의 구조면 새벽 3시에 마주하는 두 가지 질문, 즉 작업이 완료되었는지와 어디에서 멈췄는지에 대한 답을 얻기에 충분합니다.

grep workflow:error logs/run.jsonl
jq -r 'select(.type == "workflow:error") | .error.message' logs/run.jsonl
jq -r 'select(.type == "workflow:phase:end") | [.phase, .durationMs] | @tsv' logs/run.jsonl
jq -r 'select(.type == "log") | .message' logs/run.jsonl

현재 진행 중인 실행을 확인하려면 tail -f logs/run.jsonl | jq -c 'select(.type == "log")' 파일을 팔로우하십시오. 한 번의 실행으로 기록되는 라인 수는 적지만 파일은 계속 커지기만 하므로, 타이머가 몇 주 동안 실행된 후에는 ~/workflows/logs/*.jsonl에 대한 logrotate 규칙을 추가하십시오.

systemd에서 실행하기

장기 실행 데몬 대신 oneshot 서비스와 타이머를 사용합니다. 그래프는 시작되고, 실행을 마친 뒤 종료됩니다. /etc/systemd/system/log-triage.service을 작성하고 deploy를 사용자의 계정으로 교체하십시오.

[Unit]
Description=Log triage workflow
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
User=deploy
WorkingDirectory=/home/deploy/workflows
Environment=HOME=/home/deploy
Environment=PATH=/home/deploy/.bun/bin:/home/deploy/.npm-global/bin:/usr/local/bin:/usr/bin:/bin
ExecStart=/home/deploy/.bun/bin/deer-workflow run ./log-triage.ts --input-file ./input.json --print
StandardOutput=append:/home/deploy/workflows/logs/run.jsonl
StandardError=journal
TimeoutStartSec=3600

그다음 /etc/systemd/system/log-triage.timer를 실행합니다.

[Unit]
Description=Run the log triage workflow every night

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true

[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl start log-triage.service
systemctl status log-triage.service
sudo systemctl enable --now log-triage.timer
systemctl list-timers log-triage.timer

먼저 수동으로 서비스를 시작하십시오. 정상적으로 실행되면 유닛이 성공적으로 비활성화되고, logs/run.jsonl에는 workflow:end으로 끝나는 이벤트 블록이 추가됩니다. 그 후에 타이머를 활성화하십시오. list-timers은 다음 예정된 실행 시간을 출력하며, Persistent=true는 서버가 꺼져 있을 때 놓친 실행이 다음 부팅 시 한 번 수행됨을 의미합니다. StandardOutput=append:은 이벤트 스트림을 파일로 보내고 저널에는 나머지 로그만 남기므로, journalctl -u log-triage.service을 계속 읽기 쉬운 상태로 유지할 수 있습니다.

왜 셸에서는 그래프가 작동하는데 systemd에서는 실패합니까?

다음 네 가지 항목을 이 순서대로 확인하십시오.

유닛이 바이너리를 찾을 수 없습니다. systemd는 ~/.bashrc를 읽지 않으며, 기본 PATH에는 ~/.bun/bin이나 ~/.npm-global/bin가 포함되어 있지 않습니다. 유닛은 1초도 안 되어 실패하며, journalctl -u log-triage.service는 명령 이름 실행에 실패했음을 보여줍니다. 이것이 ExecStart에서 절대 경로를 사용하는 이유이며, Environment=PATH=에 두 디렉터리가 모두 나열되어 있는 이유입니다. 런타임 자체가 에이전트 단계를 시작할 때 codex 또는 claude를 찾아야 하기 때문입니다.

에이전트가 자격 증명을 찾을 수 없습니다. 에이전트 CLI는 홈 디렉터리에서 로그인 정보를 읽으므로, User=Environment=HOME=을 명시적으로 설정하고 본인이 로그인할 때 사용한 홈 디렉터리를 지정하십시오. workflow:start에 도달한 후 본인의 코드가 아닌 에이전트 CLI에서 생성된 workflow:error 메시지가 출력된다면 거의 항상 이 문제입니다.

실행이 90초 후에 강제 종료됩니다. Type=oneshot의 경우, systemd는 전체 명령에 시작 타임아웃을 적용하며 기본값은 90초입니다. 에이전트 그래프는 수 분이 소요될 수 있습니다. 저널에는 Start operation timed out. Terminating.가 기록되고 유닛은 실패 상태로 종료되며, 로그 파일에는 workflow:end 없이 실행 중간까지만 기록됩니다. TimeoutStartSec=3600을 사용하여 1시간의 여유를 주십시오. 시간 제한으로 인해 종료되는 것을 원치 않는다면 infinity을 사용하십시오.

상대 경로가 다른 곳을 참조합니다. ./log-triage.ts./input.jsonWorkingDirectory을 기준으로 합니다. 해당 줄을 생략하면 systemd는 /에서 프로세스를 시작하는데, 그곳에는 해당 파일들이 존재하지 않습니다.

오케스트레이터의 허용 권한

타이머에 맞춰 에이전트 단계를 실행하는 오케스트레이터는 관리자의 감시 없이 서버에서 동작하는 프로세스입니다. 두 가지 제어 요소와 한 가지 예산 관리가 중요합니다.

첫 번째 제어 요소는 각 agent() 호출에 적용되는 샌드박스입니다. 로그, 메트릭, 요약 대상 리포지토리 등 읽기 작업만 수행하는 단계에는 read-only를 기본값으로 설정하는 것이 적절합니다. 쓰기 작업이 반드시 필요한 단계라면 workspace-write로 전환하되, danger-full-access을 사용하는 대신 additionalWritableDirectories을 통해 쓰기 가능 영역을 최소화하십시오.

두 번째 제어 요소는 사람입니다. 메일 발송, 자금 이체, 데이터 삭제, 운영 환경 설정 변경과 같은 작업은 절대 무인 상태로 실행해서는 안 됩니다. 코드 기반 그래프에서는 단계가 코드 한 줄로 정의되므로 게이트를 배치하기 쉽습니다. 실행을 멈추고 제안된 작업을 기록한 뒤, 사람의 승인을 기다렸다가 계속 진행하십시오. 에이전트 작업 앞에 승인 게이트 배치하기에서 해당 패턴을 상세히 다루고 있으며, 타이머로 시작되는 모든 그래프에는 이 패턴을 적용해야 합니다.

예산은 비용과 직결됩니다. 모든 agent() 호출은 완전한 에이전트 세션이며, parallel()는 여러 세션을 동시에 시작합니다. 따라서 12개의 분기로 확장되는 그래프는 보고서를 읽는 사람이 있든 없든 매일 밤 12개의 세션을 실행합니다. VPS에서 AI 에이전트 비용 제어하기에 명시된 측정 및 제한 사항을 예약된 그래프에 직접 적용하십시오.

런타임을 업그레이드하기 전에 변경 로그를 읽고, 새로운 특정 버전을 설치한 뒤, --print을 사용하여 수동으로 그래프를 한 번 실행하십시오. 이처럼 초기 단계의 프로젝트에서는 CLI 인터페이스가 계속 변경됩니다. 예를 들어 Unreleased 섹션에서는 이미 0.2.0 버전에 존재하는 명령어를 삭제했습니다. 타이머로 동작하는 그래프의 신뢰성은 고정한 버전과 마지막으로 직접 확인한 실행 결과에 달려 있습니다.

FAQ

Bun이 필요한가요, 아니면 Node.js로도 Deer Workflow를 실행할 수 있나요?

Bun을 설치하십시오. 배포된 패키지는 deer-workflow 바이너리가 src/cli.ts(TypeScript 소스 파일)을 가리키도록 설정되어 있으며, 문서에서도 Bun을 필수 요구 사항으로 명시합니다. Bun은 TypeScript를 직접 실행하므로 별도의 빌드 단계가 필요하지 않습니다. sudo apt install -y unzip 뒤에 curl -fsSL https://bun.com/install | bash를 입력하여 설치하고, bun --version으로 설치를 확인하십시오. Codex CLI를 npm으로 설치하는 경우에는 별도로 Node.js와 npm이 필요합니다.

워크플로우가 터미널에서는 잘 작동하는데 왜 systemd에서는 실패하나요?

대부분 PATH, HOME 설정 문제이거나 시작 시간 초과 때문입니다. systemd는 사용자의 셸 프로필을 읽지 않으므로, ExecStart에는 deer-workflow의 절대 경로가 필요하며, Environment=PATH=에는 codex 또는 claude이 포함된 디렉터리가 지정되어야 합니다. 에이전트 CLI는 $HOME에서 자격 증명을 읽어오므로, User=Environment=HOME=를 로그인한 계정으로 설정하십시오. 또한 Type=oneshot는 기본적으로 90초의 시작 시간 초과가 적용되어 에이전트 실행이 도중에 중단되고 저널에 Start operation timed out. Terminating.이 남을 수 있으므로, TimeoutStartSec=3600을 설정하십시오.

특정 단계에서 Codex 대신 Claude Code를 사용하려면 어떻게 하나요?

일반 agent() 헬퍼는 기본 런타임인 Codex를 사용합니다. 패키지에서 ClaudeAgent를 가져와 구성한 뒤, Claude Code가 처리하게 할 단계에서 .run()을 호출하십시오. --agent codex|claude|pi 플래그는 설명으로부터 워크플로우 파일을 생성하는 명령인 deer-workflow create에 속하며, deer-workflow run에는 영향을 주지 않습니다. 어떤 에이전트를 사용하든 해당 CLI가 설치되어 있어야 하며, 서비스가 실행되는 동일한 사용자로 로그인되어 있어야 합니다.

Deer Workflow의 어떤 버전을 설치해야 하나요?

테스트를 마친 정확한 버전을 설치하십시오. 2026년 8월 19일 기준으로 최신 배포 버전은 2026년 7월 27일에 출시된 0.2.0이며, 저장소에는 47개의 커밋이 있습니다. 설치 명령에 @0.2.0(또는 이 문서를 읽는 시점의 최신 버전)를 기입하고, 해당 번호를 그래프와 함께 git에 기록해 두십시오. 업그레이드 후에는 타이머가 다시 작동하기 전에 수동으로 그래프를 한 번 실행해 보시기 바랍니다.