본문으로 건너뛰기
프로젝트 목록

PF-06 · AI · FastAPI

AetherCrew: AI 직원 11명의 가상 회사

직접 만든 오케스트레이터로 AI 직원 11명의 업무 배정, 모델 선택, 비용 추적을 구현한 가상 회사입니다. 에이전트 작업은 시뮬레이션이며 언어 모델 API는 호출하지 않습니다.

역할
설계 · 구현
기간
개인 프로젝트 · 2026.11 공개
CSP
해당 없음
규모
AI 직원 11명 · 3개 부서 · 대시보드 8페이지
핵심 기술
Python · FastAPI · WebSocket · pytest · Slack · Jira · GitHub
GitHub
11
AI 직원
3
부서
8
웹 대시보드 페이지

한눈에 보기

CEO사용자 지시경영기술영업Emma비서/경영기획실장Mia재무Ava인사Sophia기술실장Noah시니어 엔지니어Luna엔지니어EthanDB 엔지니어LiamQA 엔지니어Chloe보안 엔지니어James기획·영업실장Olivia콘텐츠 마케터(기본비활성)모델 우선순위 · 예상 비용 기록시뮬레이션: 업무 배정, 모델 선택, 비용 기록만 수행합니다언어 모델 API는 호출하지 않습니다
공개 코드에서 에이전트 작업은 시뮬레이션이며 언어 모델 API는 호출하지 않습니다.

문제

여러 AI 직원이 역할별로 일을 나눠 맡으면 누가 어떤 모델을 쓰는지, 비용이 어디까지 갔는지, 외부 시스템에 무엇을 쓸 수 있는지 코드로 통제해야 합니다.

접근

CEO 지시를 비서(경영기획실장)가 받아 계획을 쓰고 역할별 Task로 나눕니다. 직원별로 Anthropic, OpenAI, Google, DeepSeek 모델의 우선순위를 두고 실패하면 다음 모델로 전환합니다. 예상 비용을 쌓아 80%와 95%에서 경고하고 100%에서 작업을 막습니다. 외부 쓰기는 기본 차단, 파일 접근은 프로젝트 루트로 제한합니다.

결과

FastAPI 웹 대시보드 8페이지에서 조직도, 비용, 로그, 픽셀 오피스 CCTV를 봅니다. API 키 없이 실행되고 언어 모델은 호출하지 않으므로 실제 작업 결과물은 나오지 않습니다. Slack, Jira, GitHub 클라이언트는 실제 코드이며 INTEGRATIONS_LIVE_WRITE를 켤 때만 동작합니다.

자세히 보기

직원별 모델 폴백우선순위 목록 앞에서부터 사용 가능한 모델을 고릅니다gpt-5OpenAIclaude-opus-4Anthropicgemini-2.5-proGoogledeepseek-v3DeepSeek1순위2순위3순위4순위선택됨agent.fallback 이벤트 기록예상 비용만 기록, 언어 모델 API 호출 없음
전환은 agent.fallback 이벤트로 기록됩니다. 모델 호출은 시뮬레이션입니다.
예산 정책80% 경고95% 경고100% 작업 차단작업 차단
100%에 도달하면 작업을 막습니다. 비용 조회는 일·주·월·직원별로 합니다.

모델 폴백

이 코드가 하는 일: 직원의 모델 우선순위 목록과 사용할 수 없는 모델 목록을 받아, 앞에서부터 차례로 확인해 사용 가능한 첫 모델을 고릅니다. 건너뛴 모델은 fallbacks에 기록해 몇 번째 모델로 넘어갔는지 남기고, 목록이 비어 있거나 모든 모델을 쓸 수 없으면 조용히 넘어가지 않고 오류를 냅니다. 목록 길이만큼만 확인하므로 폴백이 끝없이 이어지지 않습니다.

class FallbackManager:
    """Selects next available agent with bounded fallback traversal."""

    def select(
        self,
        priority_list: list[str],
        unavailable_agents: set[str] | None = None,
    ) -> FallbackResult:
        if not priority_list:
            raise ValueError("priority_list must not be empty")
        blocked = unavailable_agents or set()
        fallbacks: list[str] = []
        for idx, model in enumerate(priority_list):
            if model in blocked:
                fallbacks.append(model)
                continue
            return FallbackResult(selected_agent=model, selected_index=idx, fallbacks=fallbacks)
        raise RuntimeError("All agents are unavailable; fallback exhausted")

예산 상태

이 코드가 하는 일: 기록된 비용을 모두 더해 예산 대비 사용률을 계산하고, 그 값에 따라 OK, WARN_80, WARN_95, HARD_STOP 네 상태 중 하나를 돌려줍니다. 예산이 0 이하로 설정되면 사용률을 100%로 보아 바로 HARD_STOP이 되므로, 예산 설정 실수가 무제한 실행으로 이어지지 않습니다. 오케스트레이터는 이 상태가 HARD_STOP이면 새 작업을 막습니다.

    @property
    def total_cost(self) -> float:
        return round(sum(e.cost_usd for e in self.entries), 6)

    def percent_used(self) -> float:
        if self.budget_policy.total_budget <= 0:
            return 100.0
        return (self.total_cost / self.budget_policy.total_budget) * 100

    def budget_state(self) -> str:
        pct = self.percent_used()
        if pct >= self.budget_policy.hard_stop_at_pct:
            return "HARD_STOP"
        if pct >= self.budget_policy.warn_at_pct[1]:
            return "WARN_95"
        if pct >= self.budget_policy.warn_at_pct[0]:
            return "WARN_80"
        return "OK"

배운 점

실제로 에이전트끼리 일을 넘기게 해 보니, 한 에이전트의 잘못된 결과를 다음 에이전트가 검증 없이 그대로 믿었습니다. 그때 신뢰 경계와 권한 범위는 프롬프트의 당부가 아니라 코드 안에 있어야 한다는 것을 체감했습니다. 그래서 이 프로젝트에서는 모델 선택, 예산 차단, 외부 쓰기, 파일 접근 범위처럼 위험이 생길 수 있는 지점을 모두 코드의 규칙으로 두었습니다. 외부 쓰기는 기본으로 막고 설정을 켤 때만 허용하며, 예산은 80%와 95%에서 경고하고 100%에서 멈춥니다. AI가 많은 일을 맡을수록 사람이 정해야 하는 것은 무엇을 시킬지보다 어디까지 허용할지라는 점을 배웠습니다.

관련 현장 노트

Open to work · 클라우드 인프라/보안

테마 고르기

사원증을 누르면 그 테마로, 보던 내용과 같은 곳으로 이동합니다. 끌면 흔들리기만 합니다.

처음 화면으로 →