메뉴
HN
Hacker News 28일 전

차세대 자율 에이전트를 위한 TypeScript 프레임워크, Flue

IMP
7/10
핵심 요약

Flue는 단순한 SDK가 아닌, 강력하고 자율적인 AI 에이전트를 구축하기 위한 TypeScript 기반 프레임워크입니다. 개발자는 코드를 한 번 작성하면 CLI, 로컬 환경, CI, 그리고 HTTP 서버 어디든 배포할 수 있으며, 에이전트의 핵심 결정을 완벽하게 통제할 수 있습니다. 기존의 범용적인 off-the-shelf AI 도구들을 대체하여 개발자가 직접 맞춤형 에이전트를 설계하고 통제할 수 있도록 지원합니다.

번역된 본문

에이전트 하네스 프레임워크(Agent Harness Framework)

이것은 또 다른 SDK가 아닙니다. Flue의 프로그래밍 가능한 TypeScript 하네스를 사용하여 강력하고 자율적인 에이전트를 구축하세요. 한 번 작성하여 어디에나 배포하세요.

README.md 및 agents/triage.ts 파일 보기 flue run triage POST /agents/triage/:id

export default async function ({ init, payload, env }) {
  // 새로운 에이전트를 초기화합니다.
  // 호스팅된 샌드박스를 제공하거나, Flue의 내장 가상 샌드박스를 사용할 수 있습니다.
  const agent = await init({ model: 'anthropic/claude-sonnet-4-6' });
  const session = await agent.session();

  // 스킬(Skills)을 재사용 가능한 워크플로우로 호출하여 구조화된 출력(structured output)을 얻습니다:
  const triage = await session.skill('triage', {
    args: { issueNumber: payload.issueNumber },
    result: v.object({ fixApplied: v.boolean() }),
  });

  // Claude Code나 Codex처럼 세션 내에서 작업을 추적합니다:
  const comment = await session.prompt('Write a GitHub comment summarizing the triage.');

  // 에이전트의 가장 중요한 결정에 대해 절대적인 통제권을 유지합니다:
  if (triage.fixApplied) {
    await session.shell('git add -A && git commit --file -', {
      stdin: `fix: ${triage.summary}`
    });
  }

  // 세밀한 제어를 통해 민감한 토큰과 API 키를 보호합니다:
  await session.shell(`gh issue comment ${Number(payload.issueNumber)} --body-file -`, {
    stdin: comment,
    env: { GITHUB_TOKEN: env.GITHUB_TOKEN },
  });
}

에이전트 = 모델(Model) + 하네스(Harness)

이것은 Claude Code 및 Codex와 같은 코딩 에이전트를 매우 강력하게 만드는 아키텍처입니다. 이들은 계획하고, 컨텍스트를 수집하며, 파일을 작성하고, 하위 에이전트를 생성하고, 역할을 채택하며, 문제를 해결할 수 있습니다. 이러한 에이전트는 단순한 챗봇 이상입니다.

그렇다면 왜 모든 에이전트가 이런 방식으로 구축되지 않을까요?

Flue는 차세대 에이전트를 위한 프레임워크입니다. Flue의 프로그래밍 가능한 에이전트 하네스는 단순한 챗봇부터 전체 코딩 플랫폼에 이르기까지 모든 자율 에이전트나 워크플로우를 표현할 수 있습니다.

즐겨 사용하는 원격 샌드박스를 연결하거나, 구성이 필요 없는(zero-config) 우리의 내장 가상 샌드박스를 사용하여 에이전트에게 모든 작업을 처리할 공간을 제공하세요.

배포할 준비가 되면, Flue는 에이전트를 HTTP 서버로 번들링하여 어디든 배포할 수 있게 해줍니다. 또는 서버를 건너뛰고 CLI에서 직접 에이전트를 실행할 수도 있으며, 이는 로컬 작업과 CI에 매우 적합합니다.

현대적인 에이전트 아키텍처

04 / 파일시스템: 읽기(read) · 쓰기(write) · 검색(grep) · 탐색(glob) 03 / 샌드박스: 배시(bash) · 보안(security) · 네트워크(network) 02 / 하네스: 스킬(skills) · 메모리(memory) · 세션(sessions) 01 / 모델: 토큰(tokens) · 도구(tools) · 프롬프트(prompts)

단 22줄의 TypeScript로 나만의 AI 이슈 분류(Issue Triage) 도구를 구축하세요. (Dosu, Greptile, CodeRabbit 대체 가능)

Flue는 직관적이고 프로그래밍 가능한 인터페이스를 통해 더 똑똑한 에이전트를 구축할 수 있는 빌딩 블록을 제공합니다. 개발자는 에이전트, 하네스, 샌드박스 자체에 이르는 전체 스택을 직접 소유하게 됩니다. 이 모든 것을 연결하고 더 강력하고 자율적인 에이전트 구축을 시작하세요.

다른 사람의 에이전트를 빌리는 것을 멈추세요.

기성(Off-the-shelf) AI 도구는 일반 대중을 위해 만들어지며, 제품, 데이터, 고객 또는 정확한 워크플로우에 맞게 조정하는 데는 한계가 있습니다.

[기능 탭: 이슈 분류 (AI issue triage, 22줄) | 데이터 분석가 (data analyst, 16줄) | 코딩 에이전트 (coding agent, 13줄, Devin/Claude Code 대체) | 고객 지원 에이전트 (customer support agent, 12줄)]

import type { FlueContext } from '@flue/sdk/client';
import { Octokit } from '@octokit/core';
import * as v from 'valibot';

// `flue run` CLI를 통해 CI에서 트리거됩니다. — HTTP 엔드포인트가 필요 없습니다.
export const triggers = {}; // Built for: Node, GitHub Actions

export default async function ({ init, payload, env }: FlueContext) {
  const { issueNumber } = payload;
  const agent = await init({ model: 'anthropic...' });
  // 이후 로직 수행...
}
원문 보기
원문 보기 (영어)
The Agent Harness Framework Not another SDK. Build powerful, autonomous agents with Flue's programmable TypeScript harness. Write once, deploy anywhere. View README.md agents/triage.ts flue run triage POST /agents/triage/:id export default async function ({ init , payload , env }) { // Initialize a new agent. // Provide a hosted sandbox, or use Flue's built-in virtual sandbox. const agent = await init ({ model: 'anthropic/claude-sonnet-4-6' }); const session = await agent. session (); // Call skills as reusable workflows with structured output: const triage = await session. skill ( 'triage' , { args: { issueNumber: payload.issueNumber }, result: v. object ({ fixApplied: v. boolean () }), }); // Keep track of work in the session, just like Claude Code or Codex: const comment = await session. prompt ( 'Write a GitHub comment summarizing the triage.' ); // Keep absolute control over the agent's most critical decisions: if (triage.fixApplied) { await session. shell ( 'git add -A && git commit --file -' , { stdin: `fix: ${ triage . summary }` }); } // Protect your sensitive tokens and API keys with fine-grained control: await session. shell ( `gh issue comment ${ Number ( payload . issueNumber ) } --body-file -` , { stdin: comment, env: { GITHUB_TOKEN: env. GITHUB_TOKEN }, }); } Agent = Model + Harness It's the architecture that makes coding agents like Claude Code and Codex so powerful. They can plan, gather context, write files, spawn subagents, adopt roles, and problem-solve. These agents are more than just chatbots. Why isnt every agent built like this? Flue is a framework for the next generation of agents. Flue's programmable agent harness is able to represent any autonomous agent or workflow, from simple chatbots to entire coding platforms. Connect your favorite remote sandbox, or use our built-in zero-config virtual sandbox to give your agent a place to work through any task. When you're ready to ship, Flue bundles your agents into an HTTP server that you can deploy anywhere. Or skip the server and run your agents right from the CLI, perfect for local tasks and CI. Modern Agent Architecture 04 / Filesystem read · write · grep · glob 03 / Sandbox bash · security · network 02 / Harness skills · memory · sessions 01 / Model tokens · tools · prompts Build your own AI issue triage in 22 lines of TypeScript. Replaces Dosu Greptile CodeRabbit Flue gives you the building blocks to build smarter agents with an intuitive, programmable interface. You own the entire stack: the agent, the harness, and the sandbox itself. Connect it all together and start building a more powerful, autonomous agent. Stop renting someone else's agent. Off-the-shelf AI tools are built for a general audience and struggle to fit to your product, your data, your customers, or your exact workflows. button]:flex-1" id="build-badges" data-tabdata="{"triage":{"label":"AI issue triage","lines":22,"replaces":["Dosu","Greptile","CodeRabbit"]},"data":{"label":"data analyst","lines":16,"replaces":["Tableau AI","Power BI Copilot","ThoughtSpot Sage"]},"coding":{"label":"coding agent","lines":13,"replaces":["Devin","Claude Code","Cursor Background Agents"]},"support":{"label":"customer support agent","lines":12,"replaces":["Intercom AI","Zendesk AI","Ada"]}}"> Issue Triage Data Analyst Coding Agent Support Agent import type { FlueContext } from '@flue/sdk/client' ; import { Octokit } from '@octokit/core' ; import * as v from 'valibot' ; // Triggered in CI via `flue run` CLI — no HTTP endpoint needed. export const triggers = {}; // Built for: Node, GitHub Actions export default async function ({ init , payload , env } : FlueContext ) { const { issueNumber } = payload; const agent = await init ({ model: 'anthropic/claude-opus-4-7' }); const session = await agent. session (); // Run the 'triage' skill to triage the GitHub issue. const triage = await session. skill ( 'triage' , { args: { issueNumber }, result: v. object ({ severity: v. picklist ([ 'low' , 'medium' , 'high' , 'critical' ]), reproducible: v. boolean (), summary: v. string (), }), }); // Post the triage result back to GitHub. // The agent/sandbox never sees your sensitive GITHUB_TOKEN. const body = `**Severity:** ${ triage . severity } \n **Reproducible:** ${ triage . reproducible } \n\n ${ triage . summary }` ; await ( new Octokit ({ auth: env. GITHUB_TOKEN })). request ( 'POST /repos/{owner}/{repo}/issues/{num}/comments' , { owner: 'withastro' , repo: 'flue' , num: issueNumber, body }, ); } import type { FlueContext } from '@flue/sdk/client' ; import { Bash, InMemoryFs, MountableFs, ReadWriteFs } from 'just-bash' ; // POST /agents/data/:id export const triggers = { webhook: true }; // Built for: Node export default async function ({ init , payload } : FlueContext ) { // Mount the current directory at /workspace, so the agent can read, // write, grep, and glob from your project files using bash. const fs = new MountableFs ({ base: new InMemoryFs () }); fs. mount ( '/workspace' , new ReadWriteFs ({ root: process. cwd () })); // Create a custom virtual sandbox with 'just-bash'. Enable Python use // so the agent can write code to analyze data, generate reports, etc. const agent = await init ({ sandbox : () => new Bash ({ fs, cwd: '/workspace' , python: true }), model: 'anthropic/claude-sonnet-4-6' , }); const session = await agent. session (); // Prompt! The agent harness includes your workspace AGENTS.md, // skills, and roles (aka subagents) to analyze the data and // complete your task as desired. return await session. prompt ( `Answer this user question: ${ payload . message }` , { role: 'data-analyst' }, ); } import type { FlueContext } from '@flue/sdk/client' ; import { Daytona } from '@daytona/sdk' ; import { daytona } from '@flue/connectors/daytona' ; // POST /agents/code/:id export const triggers = { webhook: true }; // Built for: Node, Daytona export default async function ({ init , payload , env } : FlueContext ) { // Each agent gets a real container via Daytona. const client = new Daytona ({ apiKey: env. DAYTONA_API_KEY }); const sandbox = await client. create (); const agent = await init ({ sandbox: daytona (sandbox), model: 'openai/gpt-5.5' }); const session = await agent. session (); // Setup the sandbox (for illustrative purposes only). // In production, you'd want to bake setup into the container image, // or use a snapshot (if available from your sandbox provider). await session. shell ( `git clone ${ payload . repo } /workspace/project` ); await session. shell ( 'npm install' , { cwd: '/workspace/project' }); return await session. prompt (payload.prompt); } import { getVirtualSandbox } from '@flue/sdk/cloudflare' ; import type { FlueContext } from '@flue/sdk/client' ; // POST /agents/support/:id export const triggers = { webhook: true }; // Built for: Cloudflare Workers, R2 export default async function ({ init , payload , env } : FlueContext ) { // Mount your R2 bucket (declared as a binding in wrangler.jsonc) as // the agent's filesystem at /workspace, backed by Durable Object // SQLite + R2 under the hood. The agent searches it with bash — // grep, glob, read — without spinning up a container. const sandbox = await getVirtualSandbox (env. KNOWLEDGE_BASE_BUCKET ); const agent = await init ({ sandbox, model: 'openrouter/moonshotai/kimi-k2.6' }); const session = await agent. session (); // Prompt! The agent harness includes your workspace AGENTS.md, // skills, and roles (aka subagents) to complete your task as // desired. Use `session.skill()` to call a skill directly. return await session. prompt ( `Respond to this customer message: ${ payload . message }` , { role: 'support-agent' }, ); } Deploy Anywhere Node.js Cloudflare Workers GitHub Actions GitLab CI/