오늘도 공부
Flue : 하네스 AI 에이전트 본문
Flue란?
Flue는 TypeScript로 AI 에이전트를 만들기 위한 프레임워크입니다.
Claude Code 같은 코딩 에이전트가 사용하는 하네스 기반 아키텍처를 채택하고 있으며, 다양한 AI 모델을 에이전트처럼 사용할 수 있게 해줍니다.
Flue의 기반에는 Pi라는 “minimal terminal coding harness”가 사용됩니다. Pi는 터미널에서 코딩 에이전트를 실행하는 데 필요한 최소 기능을 제공하는 하네스이고, Flue는 이를 바탕으로 더 고급 에이전트 구축과 관리를 가능하게 합니다.
Flue가 제공하는 주요 구성요소
Flue는 AI 에이전트 개발에 필요한 기능을 통합적으로 제공합니다.
구성요소설명
| 에이전트 | 컨텍스트를 유지하며 자율적으로 작업하는 AI 모델 |
| 워크플로우 | 작업을 단계별로 구조화한 프로세스 |
| instructions | 에이전트의 행동 규칙, 시스템 프롬프트 |
| 툴 | 외부 API나 기능을 호출하기 위한 도구 |
| 스킬 | 필요할 때만 로드되는 전문 지식 또는 Runbook |
| 서브에이전트 | 메인 에이전트가 작업을 위임하는 전문 에이전트 |
| MCP 서버 | 외부 서비스와 연결하기 위한 Model Context Protocol 인터페이스 |
| 샌드박스 | 안전하게 코드를 실행하는 격리 환경 |
| 옵저버빌리티 | 로그, 메트릭, 실행 상태 모니터링 |
| 채널 | Slack, Discord, Teams 등과 연결하는 인터페이스 |
핵심 특징
1. Durable Execution, 즉 중단 후 재개 가능
AI 에이전트 작업은 오래 걸릴 수 있고 중간에 에러가 날 수 있습니다.
Flue는 세션 기록과 컨텍스트를 스토리지에 저장해서 작업을 중간부터 재개할 수 있게 합니다.
예를 들어 Cloudflare Workers에서 실행할 경우, 세션 정보와 컨텍스트를 Durable Object에 저장할 수 있습니다.
Flue 프로젝트 생성 방식
기본 설정 흐름은 다음과 같습니다.
mkdir flue-agent-example
cd flue-agent-example
npm init -y
npm install @flue/runtime@latest
npm install @flue/cli@latest --save-dev
npx flue init --target node
그러면 flue.config.ts가 생성됩니다.
import { defineConfig } from '@flue/cli/config';
export default defineConfig({
target: 'node',
});
환경변수에는 AI 모델 API 키를 넣습니다.
OPENAI_API_KEY=your_openai_api_key
기본 에이전트 예시
Flue에서는 에이전트를 src/agents 디렉터리에 배치합니다.
파일 이름이 에이전트 이름으로 사용됩니다.
예시:
import { defineAgent, type AgentRouteHandler } from '@flue/runtime';
export const description = "最初のエージェントです。ユーザーの質問に博多弁で答えます。";
export const route: AgentRouteHandler = async (_c, next) => next();
export default defineAgent(() => ({
model: "openai/gpt-5.4-nano",
instructions: "あなたは優秀なアシスタントです。博多弁でユーザーの質問に答えてください。",
}));
실행:
npx flue run my-first-agent --input '{ "message": "こんにちは" }'
SRE 에이전트 예시
이 글의 핵심 예시는 SRE 장애 대응 에이전트입니다.
SRE 에이전트는 다음과 같은 일을 목표로 합니다.
- 시스템 상태 확인
- 로그와 메트릭 조사
- 원인 가설 수립
- 복구 액션 제안
- 변경 작업 전 사람에게 승인 요청
중요한 점은 읽기 작업과 쓰기 작업을 분리하는 것입니다.
읽기 작업은 에이전트가 적극적으로 수행해도 됩니다.
예:
로그 확인
메트릭 확인
배포 이력 확인
서비스 상태 확인
하지만 쓰기 작업은 반드시 사람의 승인이 필요합니다.
예:
롤백
배포
스케일 조정
설정 변경
이 부분이 실제 운영 환경에서 매우 중요합니다.
instructions를 Markdown으로 분리
처음에는 instructions를 코드 안에 직접 작성했지만, 실제 에이전트에서는 시스템 프롬프트가 길어지기 때문에 Markdown 파일로 분리하는 방식을 권장합니다.
예:
import instructions from './sre-agent.md' with { type: 'markdown' };
export default defineAgent(() => ({
model: "openai/gpt-5.4-nano",
instructions,
}));
이 방식은 프롬프트를 별도 문서처럼 관리할 수 있어 유지보수에 유리합니다.
툴 정의
SRE 에이전트가 로그나 서비스 상태를 확인하려면 툴이 필요합니다.
예를 들어 get-logs 툴은 특정 서비스의 최근 로그를 가져옵니다.
export const getLogsTool = defineTool({
name: "get-logs",
description: "지정한 서비스의 최근 로그를 가져온다.",
input: v.object({
service: v.string(),
level: v.optional(v.picklist(["error", "warn", "info"])),
limit: v.optional(v.number()),
}),
async run({ input }) {
const { service, level, limit = 20 } = input;
const entries = queryLogs(service, level, limit);
return { service, count: entries.length, entries };
},
});
툴은 에이전트의 tools 배열에 추가합니다.
export default defineAgent(() => ({
model: "openai/gpt-5.4-nano",
instructions,
tools: [getLogsTool, getServiceStatusTool],
}));
Runbook을 스킬로 정의
운영 장애 대응에서는 Runbook, 즉 장애 대응 절차서가 중요합니다.
하지만 모든 Runbook을 항상 시스템 프롬프트에 넣으면 컨텍스트가 커지고, 관련 없는 절차가 섞여 에이전트가 잘못된 판단을 할 수 있습니다.
그래서 Flue는 Runbook을 스킬로 정의할 수 있습니다.
스킬은 평소에는 description만 로드되고, 에이전트가 필요하다고 판단할 때 전체 내용을 불러옵니다.
이 방식을 progressive disclosure라고 설명합니다.
예:
import paymentsRunbook from "../skills/payments-runbook/SKILL.md" with { type: "skill" };
export default defineAgent(() => ({
model: "openai/gpt-5.4-nano",
instructions,
tools: [getLogsTool, getServiceStatusTool],
skills: [paymentsRunbook],
}));
즉, payments-api 장애가 발생했을 때만 payments-runbook을 로드해서 대응 절차를 참고하게 할 수 있습니다.
서브에이전트
장애 조사는 로그, 메트릭, 배포 이력, DB 상태 등 여러 정보를 다뤄야 합니다.
모든 정보를 메인 에이전트가 직접 읽으면 컨텍스트가 오염되고 길어질 수 있습니다.
그래서 Flue에서는 서브에이전트를 사용할 수 있습니다.
예:
서브에이전트역할
| log-analyst | 로그만 조사하고 요약 |
| metrics-analyst | 메트릭만 조사하고 요약 |
| 메인 SRE 에이전트 | 요약을 종합해 최종 판단 |
로그 전문 서브에이전트 예시:
export const logAnalyst = defineAgentProfile({
name: "log-analyst",
description: "로그 전문 조사 서브에이전트입니다.",
model: "openai/gpt-5.4-nano",
instructions: "get-logs를 사용해 로그를 읽고 이상 징후만 요약하세요.",
tools: [getLogsTool],
});
메인 에이전트에 연결:
export default defineAgent(() => ({
model: "openai/gpt-5.4-nano",
instructions,
tools: [getServiceStatusTool],
skills: [paymentsRunbook],
subagents: [logAnalyst],
}));
이렇게 하면 메인 에이전트는 원본 로그 전체를 직접 읽지 않고, 요약만 받아 최종 판단을 합니다.
워크플로우
Flue의 워크플로우는 작업을 여러 단계로 나눈 구조화된 처리입니다.
예시로 글에서는 장애 보고서, 즉 포스트모템 생성 워크플로우를 만듭니다.
처리 흐름은 다음과 같습니다.
- 입력받은 인시던트 정보를 incident.md로 저장
- 에이전트가 로그, 상태, 배포 이력을 조사
- postmortem.md 생성
- 생성된 문서를 다시 읽고 구조화된 요약 반환
워크플로우는 defineWorkflow로 정의합니다.
export default defineWorkflow({
agent: defineAgent(() => ({
model: "openai/gpt-5.4-nano",
sandbox: local(),
cwd: "postmortems",
tools: [getServiceStatusTool, getLogsTool, getDeployHistoryTool],
})),
input: v.object({
service: v.string(),
incident: v.string(),
}),
output: v.object({
markdown: v.string(),
rootCause: v.string(),
actionItems: v.array(v.string()),
}),
async run({ harness, input }) {
await harness.fs.writeFile(
"incident.md",
`# Incident: ${input.service}\n\n${input.incident}\n`,
);
const session = await harness.session();
await session.prompt(
"incident.md를 읽고 조사 후 postmortem.md를 작성하세요."
);
const markdown = await harness.fs.readFile("postmortem.md");
const summary = await session.prompt(
"postmortem.md에서 근본 원인과 재발 방지 항목을 추출하세요.",
{
result: v.object({
rootCause: v.string(),
actionItems: v.array(v.string()),
}),
},
);
return {
markdown,
rootCause: summary.data.rootCause,
actionItems: summary.data.actionItems,
};
},
});
주의할 점은 local() 샌드박스를 사용하면 호스트 파일시스템에 접근하므로 보안상 신뢰할 수 있는 환경에서만 사용해야 한다는 것입니다.
Slack 연동
Flue는 Slack, Discord, Teams 같은 외부 채팅 서비스와 연결할 수 있는 채널 기능을 제공합니다.
Slack 연동 흐름은 다음과 같습니다.
- Slack App 생성
- Bot Token, Signing Secret 발급
- 환경변수 설정
- @flue/slack, @slack/web-api 설치
- src/channels/slack.ts 생성
- Slack 이벤트를 받아 SRE 에이전트에 dispatch
- 에이전트 응답을 Slack thread에 전송
Slack 채널 예시:
import { dispatch } from '@flue/runtime';
import { createSlackChannel } from '@flue/slack';
import sreAgent from '../agents/sre-agent.ts';
export const channel = createSlackChannel({
signingSecret: process.env.SLACK_SIGNING_SECRET!,
async events({ payload }) {
if (payload.type !== 'event_callback') return;
if (payload.event.type !== 'app_mention') return;
const event = payload.event;
await dispatch(sreAgent, {
id: channel.conversationKey({
teamId: payload.team_id,
channelId: event.channel,
threadTs: event.thread_ts ?? event.ts,
}),
input: {
type: 'slack.app_mention',
eventId: payload.event_id,
text: event.text,
},
});
},
});
이후 Slack에서 다음처럼 부르면 됩니다.
@sre-agent payments-api에서 5xx가 증가하고 있으니 Runbook 기준으로 조사해줘
그러면 에이전트가 Runbook, 로그, 메트릭 등을 참고해 조사 결과를 Slack 스레드에 답변합니다.
전체 구조 요약
Flue 기반 SRE 에이전트 구조는 다음과 같이 이해하면 됩니다.
Slack / CLI / HTTP
↓
Flue Channel
↓
Main SRE Agent
↓
┌───────────────┬────────────────┬───────────────┐
│ Tools │ Skills │ Subagents │
│ 상태 확인 │ Runbook │ log-analyst │
│ 배포 이력 │ 장애 절차서 │ metrics-analyst │
└───────────────┴────────────────┴───────────────┘
↓
원인 가설 + 권장 조치 + 승인 필요 여부 보고
중요한 포인트
Flue의 강점
Flue는 단순한 LLM 호출 라이브러리가 아니라, 실제 운영 가능한 AI 에이전트 구조를 만들기 위한 프레임워크에 가깝습니다.
특히 다음 기능이 중요합니다.
- 에이전트 실행 세션 관리
- 툴 호출
- 스킬 기반 지식 로딩
- 서브에이전트 위임
- 워크플로우 구조화
- Slack 같은 외부 채널 연동
- 샌드박스 실행 환경
- 장애 대응 같은 장기 작업 지원
기존 AI SDK와의 차이
[Inference] 이 글 기준으로 보면 Flue는 Vercel AI SDK 같은 “LLM 호출 및 UI 스트리밍 중심 SDK”보다는, 에이전트 실행 환경 전체를 구성하는 프레임워크에 가깝습니다.
비교하면 다음과 같습니다.
구분Vercel AI SDKFlue
| 주 목적 | AI 앱 UI, 스트리밍, tool calling | 에이전트 실행 프레임워크 |
| 언어 | TypeScript | TypeScript |
| 에이전트 구조 | 직접 설계 필요 | Agent, Skill, Workflow, Channel 구조 제공 |
| 장기 실행 | 별도 구현 필요 | 세션 저장, 재개 구조 제공 |
| Slack 연동 | 직접 구현 | Channel 개념 제공 |
| Runbook/Skill | 직접 구현 | Skill 구조 제공 |
| 샌드박스 | 별도 구현 | 내장 개념 제공 |
개발자 관점에서의 의미
Flue는 다음과 같은 프로젝트에 적합해 보입니다.
1. 사내 운영 자동화 에이전트
예:
서버 장애 조사
로그 분석
배포 이력 확인
장애 보고서 생성
Slack 알림
2. 고객지원 에이전트
예:
고객 문의 분석
내부 문서 검색
티켓 분류
답변 초안 작성
담당자 연결
3. 개발 자동화 에이전트
예:
코드 리뷰
PR 요약
테스트 실패 분석
CI 로그 분석
릴리즈 노트 생성
4. 문서 생성 워크플로우
예:
회의록 → 요약 → 액션아이템 추출
장애 기록 → 포스트모템 작성
기획서 → PRD 변환
이 글의 핵심 결론
Flue는 TypeScript 기반의 AI 에이전트 프레임워크입니다.
에이전트, 툴, 스킬, 서브에이전트, 워크플로우, 채널, 샌드박스, 옵저버빌리티를 하나의 구조 안에서 다룰 수 있습니다.
특히 SRE 장애 대응 예제에서 Flue의 장점이 잘 드러납니다.
핵심은 다음입니다.
메인 에이전트는 판단을 담당하고,
툴은 외부 정보를 가져오고,
스킬은 필요한 전문 지식을 제공하고,
서브에이전트는 세부 조사를 담당하고,
워크플로우는 결과물을 구조화하며,
채널은 Slack 같은 외부 서비스와 연결한다.
즉 Flue는 단순히 “AI에게 질문하는 앱”을 만드는 도구가 아니라, 실제 업무 프로세스 안에서 움직이는 AI 에이전트 시스템을 만들기 위한 프레임워크라고 볼 수 있습니다.
GitHub - withastro/flue: The sandbox agent framework.
The sandbox agent framework. Contribute to withastro/flue development by creating an account on GitHub.
github.com
'AI > 추천 오픈소스' 카테고리의 다른 글
| AI 에이전트는 “모델”이 아니라 “운영 시스템”이다 (0) | 2026.06.30 |
|---|---|
| Ornith-1.0: 코딩 에이전트가 스스로 ‘일하는 방식’까지 학습하기 시작했다 (0) | 2026.06.27 |
| mattpocock/skills 에 대한 자세한 설명 (0) | 2026.06.25 |
| Loop 방식의 에이전트 (Loom) (0) | 2026.06.23 |
| AI 코딩 에이전트가 코드를 너무 많이 쓴다면: Ponytail (0) | 2026.06.19 |
