MINARA

커스텀 에이전트

시스템 프롬프트 + 스킬 + 도구 + 위험 상한 + 트리거의 저장된 번들. CLI / REPL / HTTP / 워크플로 / cron 에서 실행할 수 있습니다.

🟢 구성 가능: 커스텀 에이전트는 별도의 런타임이 아니라 레시피입니다. REPL 세션과 동일한 에이전트 루프, 동일한 스킬 레지스트리, 동일한 자금 확인 게이트 위에서 동작합니다.

커스텀 에이전트 (Custom Agent) 는 다음을 묶은 저장된 번들입니다.

  • system_prompt (에이전트 실행 시의 지시사항)
  • skill_ids 서브셋 (러너가 활성화할 DomainSkill)
  • tool_names + tool_sets 서브셋 (러너가 노출할 도구)
  • risk_tier_max 상한 (1 = 읽기 전용, 4 = 수동 전용). Web UI 마법사는 이를 읽기 전용 / 자금 이동 없음 / 자금 이동 가능 세 가지로 제시하며, 마지막 항목은 tier 3(확인 기반 현물 거래: swap, buy, sell) 또는 tier 4(영구·출금·autopilot 포함 모든 자금 작업)를 선택할 수 있습니다. 예약·이벤트 에이전트는 자금을 이동할 수 없으며, 자금 이동은 매번 확인이 필요합니다.
  • discovery_mode (러너의 자기 확장 적극성)
  • triggers 목록 (manual / cron / event)
  • 자유 형식의 metadata

이 번들은 SQLite 의 agent_definitions 테이블에 영구 저장됩니다. 실행 경로는 REPL /agents run, CLI minara agents run, HTTP POST /v1/agents/:id/runs, Web UI 의 Run 드로어, 워크플로 단계 agent_turn { agent_id }, cron / event 트리거 중 어느 것이든 가능합니다.

커스텀 에이전트는 개념적으로 Anthropic 의 Managed Agents API 보다 Claude Code subagents 에 더 가깝습니다. 메인 에이전트와 같은 프로세스 내부에서 로컬로 실행되고, 같은 스킬 카탈로그를 공유하며, 같은 안전 경계를 상속합니다. 샌드박스화된 서드파티 런타임이 아닙니다.

커스텀 에이전트 흐름: 저장된 정의가 트리거로 실행되고 런타임이 위험 상한을 제한하며, 자금 확인 게이트 뒤에서 공유 에이전트 루프로 실행되고 자율 실행이 끝나면 알려줍니다

운영자가 이것을 원하는 이유

  • 재사용: 반복되는 작업을 한 번만 인코딩합니다. "일일 ETH 모닝 브리프", "주간 포트폴리오 리뷰", "온체인 유입 감시자" 와 같이 각각이 이름이 붙은 에이전트로 존재하며 원클릭으로 실행됩니다.
  • 제한된 도구 면: 리서치용 에이전트는 읽기 전용 스킬만 있으면 충분합니다 (swap_tokens 는 불필요합니다). 트레저리 에이전트는 Hyperliquid 영구 선물만 필요합니다. 스킬셋이 작을수록 시스템 프롬프트가 타이트해지고 관련 없는 도구 호출이 줄며 턴당 토큰 비용이 낮아집니다.
  • 트리거: cron: "0 9 * * *" 가 붙은 에이전트는 운영자 개입 없이 매일 아침 실행됩니다. event: { event_name: "price.alert" } 가 붙은 에이전트는 이벤트 버스가 일치하는 이벤트를 발행할 때 실행됩니다.
  • 워크플로에서 조합 가능: 다단계 워크플로는 리서치 프롬프트를 인라인으로 넣는 대신 agent_turn { agent_id: "research-bot" } 으로 참조할 수 있습니다. 워크플로 작성자는 흐름을 소유하고, 에이전트는 추론을 소유합니다.
  • 공유 가능: ~/.minara/agents/ 에 JSON 파일을 두면 다음 부팅 시 로더가 가져옵니다. research-bot 을 팀원에게 내보내면 상대방의 인스턴스가 source: "file:..." 로 로드합니다.

세 가지 탐색 모드

discovery_mode 는 실행 시 러너가 skill_idstool_names 를 어떻게 다루는지를 제어합니다.

새 에이전트의 기본값은 free_discovery 입니다. 메인 어시스턴트처럼 에이전트가 필요한 스킬을 스스로 발견하므로 Web UI 마법사에서 미리 고를 필요가 없습니다. 도구는 선택한 스킬과 risk_tier_max 상한에서 결정되므로 tool_names, tool_sets, discovery_skill_pool 은 JSON 파일 로더나 HTTP API 로 설정하는 고급 필드이며 마법사에는 노출되지 않습니다.

constrained

하드 화이트리스트입니다. 러너는 선언된 skill_ids 만 정확히 활성화하고, 선언된 tool_names (그리고 tool_sets 합집합과의 교집합) 만 노출합니다. activate_skills 메타 도구는 비활성화되므로 LLM 이 턴 도중에 자기 확장을 수행할 수 없습니다.

운영 신뢰성이 필요하면 이 모드를 선택하십시오. 에이전트는 매번 같은 모양으로 실행됩니다. 리뷰가 쉽고, 테스트하기 쉽고, 예산을 잡기 쉽습니다.

scenario_aware

하위 호환을 위해 유지되며, 현재 동작은 constrained 와 완전히 동일합니다. 프롬프트마다 스킬을 프리로드하던 시나리오 분류기가 폐기되어, 이 모드는 선언된 skill_ids 만 실행하고 activate_skills 는 비활성화됩니다. 기존 에이전트는 값을 유지하지만, 새 에이전트는 constrained 를 선택하십시오.

free_discovery (기본값)

선언된 시드 집합에서 출발하여, LLM 이 턴 도중에 activate_skills 를 호출해서 스킬을 추가할 수 있습니다. discovery_skill_pool glob 패턴 (비어 있거나 누락이면 카탈로그 전체) 과 risk_tier_max 에 의해 제한됩니다.

신중하게 사용하십시오. 에이전트에게 해법 공간으로 전체 카탈로그를 넘겨주는 방식이라 개방형 리서치에는 강력하지만 좁고 반복적인 작업에는 취약합니다.

세 모드 모두 적용되는 안전 불변조건

  • risk_tier_max 는 upsert 시점뿐 아니라 트리거 시점 에도 러너에 의해 강제됩니다. DB 에서 직접 UPDATE agent_definitions SET risk_tier_max = 4 를 수행하더라도, cron / event / autopilot 트리거에서는 실효 상한이 2 로 클램프됩니다.
  • 자금 확인 게이트는 에이전트 실행의 컨텍스트를 읽습니다. 테스트 실행은 환경 변수 MINARA_SKIP_FUND_CONFIRM=1 이 설정되어 있어도 2 단계 확인을 강제합니다.
  • 아카이브된 에이전트는 fail-closed 입니다. 실행 중인 agent_turn 단계가 아카이브된 에이전트를 참조하는 경우 저장된 스냅샷에 대해 실행을 계속하지만, 아카이브된 id 에 대한 새 실행은 즉시 실패합니다.

트리거

각 에이전트에는 triggers 목록이 있습니다. v1 은 네 가지 종류를 제공합니다.

종류형태발화 조건
manual{ kind: "manual" }UI 에서 Run 클릭 / /agents run 입력 / POST /v1/agents/:id/runs
cron{ kind: "cron", expr: "0 9 * * *", timezone?: "UTC" }TriggerManager tick 이 cron 표현식을 통과
event{ kind: "event", filter: { event_name: "price.alert", payload_match?: {...} } }이벤트 버스가 일치 이벤트 발행
once{ kind: "once", fire_at: 1717430400000 }벽시계 시간이 fire_at (unix 밀리초) 에 도달할 때. 한 번만 발화한 뒤 에이전트가 스스로 아카이브됩니다

안전 규칙: 기본적으로 manual 이 아닌 모든 트리거는 upsert 시점에 risk_tier_max ≤ 2 를 강제하므로 예약 / 이벤트 에이전트는 자금을 이동할 수 없습니다. 에이전트는 자율 자금 이동을 켤 수 있으며 (allow_autonomous_fund_moves: true, 같은 쓰기에 confirm_autonomous_fund_moves: true 필요), 이렇게 하면 비 manual 상한이 ≤ 3 (확인 기반 현물 거래) 까지 올라갑니다. tier 4 (영구·출금·autopilot) 는 항상 수동 트리거가 필요하므로 발화 시 사람이 루프 안에 있습니다. 상한을 넘는 쓰기는 스토어가 명확한 오류와 함께 거부합니다.

once 에이전트는 리마인더의 구현 방식입니다. 한 번만 발화한 뒤 아카이브되어 다시는 발화하지 않습니다. 이미 발화한 리마인더를 복원해도 다시 실행되지 않습니다. 다시 예약하거나 (새 fire_at 설정) 수동으로 실행하세요. 반복 리마인더에는 cron 트리거를 사용합니다.

알림

실행이 끝나면 Minara 는 두 가지 방법으로 알려줍니다.

인앱 알림 센터. 오른쪽 위 종 아이콘이 읽지 않은 개수와 최근 에이전트 실행 목록을 표시하며, 각 항목은 해당 실행으로 연결됩니다. 항상 켜져 있고 실시간으로 갱신되며, 읽음 표시하거나 비울 수 있는 짧은 기록을 보관합니다.

브라우저 알림. 설정 → 일반 (또는 종 아이콘의 빠른 토글) 에서 "브라우저 알림" 을 켜면 Minara 탭이 백그라운드에 있거나 최소화되어 있을 때 OS 의 데스크톱 알림을 받습니다. Minara 탭을 보고 있을 때는 대신 인앱 메시지로 표시됩니다. 브라우저가 처음에 권한을 요청합니다. 탭을 닫거나 브라우저를 종료하면 오지 않으며, 페이지에 보안 컨텍스트 (HTTPS) 가 필요합니다. localhost 는 예외입니다.

어떤 실행이 알리는가. 에이전트가 스스로 수행하는 실행이 알립니다: 예약 (cron), 이벤트 (event), 일회성 리마인더, 워크플로 단계입니다. 직접 시작한 실행 (Run 버튼, /agents run, 채팅 턴) 은 이미 보고 있으므로 알리지 않습니다. 테스트 실행은 알리지 않습니다.

에이전트별 제어. 각 에이전트에는 "인앱 알림" 설정이 있습니다. 시끄러운 에이전트는 끄거나, 실행 실패 시에만 알리도록 선택할 수 있습니다. 새 에이전트는 기본으로 켜져 있습니다.

에이전트를 참조하는 워크플로

워크플로의 agent_turn 단계는 두 가지 형태가 있습니다.

// 권장: 기존 커스텀 에이전트를 id 로 참조
{ "kind": "agent_turn", "agent_id": "research-bot",
  "input": { "ticker": "ETH" } }

// 레거시 폴백: inline goal. 엔진이 scoped 스킬 / 도구 서브셋이 없는
// 일회용 에이전트를 즉석에서 띄웁니다
{ "kind": "agent_turn", "goal": "summarize recent ETH news" }

agent_turn { agent_id }tool_call 의 선택 기준

추론, 다중 도구 탐색, 자연어 출력이 필요한 단계에는 agent_turn 을 사용합니다. 리서치, 초안 작성, 분류, 요약이 여기에 해당합니다.

입력이 정해져 있고 동작이 확정적인 단일 단계에는 tool_call 을 사용합니다. 한 번의 스왑, 송금, 잔액 조회, 가격 조회 같은 경우입니다. 도구 호출은 더 빠르고 저렴하며, LLM 턴을 가로질러 확인 컨텍스트를 재구성할 필요 없이 기존 자금 확인 게이트를 그대로 사용합니다.

"ETH 를 숏 친 다음 전략 노트를 작성한다" 는 워크플로는 두 단계로 분리됩니다. 실행은 tool_call { tool: "open_perps_position" } 으로, 사후 분석은 agent_turn { agent_id: "strategy-note" } 으로 처리합니다.

로컬 오토메이션 스킬은 이 매트릭스를 자동으로 준수합니다. 커스텀 에이전트 카탈로그를 노출하고, "초안" / "리서치" / "요약" 의도는 agent_turn 으로, 자금 이동 의도는 tool_call 로 라우팅합니다.

CLI

minara agents 서브커맨드는 전체 라이프사이클을 노출합니다.

동작형식용도
listminara agents list [--archived]등록된 모든 에이전트 출력
getminara agents get <id>전체 정의를 JSON 으로 덤프
createminara agents create --from <file.json>JSON 파일에서 삽입
updateminara agents update <id> --from <patch.json>PATCH. 의미 있는 변경 시 version 을 올림
archiveminara agents archive <id>소프트 삭제. 부착된 트리거를 정리
runminara agents run <id> [--input "..."] [--test]애드혹 실행 시작. 이벤트를 stdout 으로 스트리밍
exportminara agents export <id>JSON 을 출력. 파일로 파이프 가능
importminara agents import [--from <file.json>]export 의 역. --from 생략 시 stdin 을 읽음

run 은 워크플로가 완료 / 실패할 때까지 동기적으로 이벤트 스트림을 열고 끝에 최종 __adhoc__ 출력 페이로드를 출력합니다. cron / 셸 스크립트와 파이프 친화적입니다.

minara agents export research-bot > research-bot.json
scp research-bot.json bob@host:~/.minara/agents/
ssh bob@host minara agents list           # research-bot 이 source=file:... 로 표시됨

REPL

/agents 슬래시 커맨드가 대화형 대응물입니다.

형식동작
/agents 또는 /agents list등록된 모든 에이전트 목록
/agents create대화형 collectArgs 플로우: 이름 → 시스템 프롬프트 → 스킬 선택
/agents run [<id>] [<input>...]에이전트 실행. <id> 생략 시 라이브 피커
/agents archive [<id>]아카이브. <id> 생략 시 라이브 피커. y/N 확인

/agents create 플로우는 표준 collectArgs 패턴을 따릅니다. 필수 필드를 하나씩 묻고, 검증 실패 시 잘못된 필드만 다시 묻고, 빈 답변이 세 번 연속이면 취소됩니다.

Web UI

Web UI 는 AUTOMATE 내비게이션 그룹 아래의 /agents 에 커스텀 에이전트를 표시합니다 (Workflows, Autopilot 과 같이 위치합니다). Web UI 의 /agents 를 참고하십시오.

  • 목록 페이지: 각 에이전트가 이름, 위험 상한, discovery 모드, 트리거 요약, 카드별 Run / Edit / Archive 액션을 담은 카드로 표시됩니다. Import 버튼은 JSON 파일 업로드를 받고, New 버튼은 마법사를 엽니다.
  • 마법사 (3 단계): 1 단계에서는 스타터 템플릿 (researcher / treasury sentinel / drafting) 또는 "빈" 을 선택합니다. 2 단계에서는 이름을 정하고 시스템 프롬프트를 작성하며, 스킬을 선택합니다 (피커는 하드 화이트리스트 모드에서만 표시됩니다). 3 단계에서는 discovery 모드, 위험 상한, 트리거 종류를 선택합니다. 안전 클램프 규칙은 인라인으로 표시됩니다.
  • 상세 페이지: Overview / Definition / History 세 개 탭. Definition 탭은 라이브 JSON 을 보여주고 PATCH 편집은 원자적으로 version 을 올립니다.
  • Run 드로어: 목록 카드 또는 상세 페이지에서 열립니다. 인라인 SSE 이벤트 스트림이 workflow:startedworkflow:step 이벤트 → 종단 workflow:completed / workflow:failed 를 표시합니다. Run as test (?test=1) 는 체크박스이며, 테스트 실행에서는 env 의 skip 설정이 있어도 자금 확인 모달이 표시됩니다.

REST 엔드포인트

HTTP gateway 는 비-CLI 통합을 위해 동일한 surface 를 노출합니다.

메소드경로용도
GET/v1/agents정의 목록 (?archived=true 는 아카이브만 반환)
POST/v1/agents생성. body 는 AgentDefinitionInput
GET/v1/agents/:id최신 정의 조회
PATCH/v1/agents/:id업데이트. body 는 부분 AgentUpdatePatch
DELETE/v1/agents/:id아카이브 (소프트 삭제, 복구 가능)
POST/v1/agents/:id/restore아카이브된 에이전트 복원 (트리거 재장착)
DELETE/v1/agents/:id/permanent영구 삭제 (되돌릴 수 없음. 실행 기록은 유지)
POST/v1/agents/:id/runs애드혹 실행 시작. ?test=1 로 테스트 모드
GET/v1/agents/:id/runs실행 이력 (워크플로 인스턴스 이력)
GET/v1/workflows/:id/instances/:iid/events/stream실행 중 인스턴스용 SSE 이벤트 스트림

SSE 엔드포인트는 Web UI Run 드로어가 사용하는 것과 동일합니다. 이벤트를 단일 instance_id 로 투명하게 필터링합니다.

예: curl 로 생성

curl -X POST http://localhost:8080/v1/agents \
  -H "Authorization: Bearer $GATEWAY_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d @research-bot.json

# 애드혹 테스트 실행 시작
curl -X POST "http://localhost:8080/v1/agents/research-bot/runs?test=1" \
  -H "Authorization: Bearer $GATEWAY_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "input": "summarize recent ETH news" }'

AgentDefinition JSON 예시

{
  "id": "research-bot",
  "name": "Daily Research Bot",
  "description": "Morning brief: trending tokens, macro context, watchlist signals.",
  "system_prompt": "You are a markets research assistant. Output a 5-bullet brief covering crypto majors, US equities open, and any flagged watchlist alerts. No advice; observation only.",
  "skill_ids": [
    "analysis.market_overview",
    "research.knowledge_base",
    "minara.core"
  ],
  "tool_names": ["get_price", "get_trending", "search_tokens"],
  "tool_sets": ["market_data"],
  "risk_tier_max": 1,
  "discovery_mode": "constrained",
  "triggers": [
    { "kind": "cron", "expr": "0 9 * * *", "timezone": "UTC" }
  ],
  "metadata": {
    "tags": ["research", "daily"],
    "owner": "[email protected]"
  }
}

참고:

  • 시장 데이터만 읽는 cron 트리거 에이전트에는 risk_tier_max: 1 (읽기 전용) 이 적합합니다. 예약 에이전트의 상한은 기본 tier 2 이며, allow_autonomous_fund_moves 를 설정하면 tier 3 입니다. 그 상한을 넘으면 upsert 가 거부됩니다.
  • discovery_mode: "constrained" 는 러너가 턴 도중에 activate_skills 를 호출하지 않음을 의미합니다. 스킬 / 도구 면이 선언된 그대로입니다.
  • tool_sets: ["market_data"] 는 해당 집합의 모든 도구를 tool_names 화이트리스트와 함께 추가합니다. 러너는 합집합을 취합니다.

agent_turn { agent_id } 가 포함된 워크플로 JSON

{
  "id": "morning-brief",
  "name": "Morning Brief",
  "version": 1,
  "steps": [
    {
      "id": "step_1",
      "kind": "tool_call",
      "tool": "get_portfolio_snapshot",
      "input": {}
    },
    {
      "id": "step_2",
      "kind": "agent_turn",
      "agent_id": "research-bot",
      "input": {
        "portfolio_summary": "{{ steps.step_1.output }}"
      }
    },
    {
      "id": "step_3",
      "kind": "tool_call",
      "tool": "send_telegram",
      "input": {
        "text": "{{ steps.step_2.output }}"
      }
    }
  ]
}

워크플로 작성자가 흐름을 배선하고 research-bot 이 추론을 소유합니다. 2 단계가 처음 실행될 때, 엔진은 에이전트 정의를 workflow_instances.agent_def_snapshot 으로 스냅샷합니다. 이후 research-bot 에 대한 PATCH 는 이 실행 중 인스턴스에 영향을 주지 않습니다. 새 실행은 새 버전을 가져옵니다.

JSON 파일 공유

에이전트 로더는 부팅 시 ~/.minara/agents/ (또는 $MINARA_DATA_DIR/agents/) 를 스캔합니다. AgentDefinition 으로 파싱되는 모든 *.json 파일은 source: "file:<절대 경로>" 로 스토어에 등록됩니다.

파일 출처 행은 PATCH 잠금 상태입니다. REST / CLI 업데이트는 명확한 오류로 거부됩니다. 디스크에서 파일을 편집한 후 에이전트를 재시작하거나 로더 동기화 엔드포인트를 호출해서 변경을 가져오십시오. 이로써 파일이 신뢰의 출처로 유지되고, 디스크와 DB 사이에 조용한 드리프트가 발생하지 않습니다.

파일을 삭제하면 다음 동기화에서 해당 행이 아카이브되므로, 파일 삭제로 이미 그 에이전트를 스냅샷한 워크플로가 깨지지 않습니다.

안전 자세 (요약)

  • 런타임 위험 클램프: manual 이 아닌 트리거 (cron / event / autopilot) 는 effective_risk_tier_max 를 2 로, allow_autonomous_fund_moves 설정 시 3 으로 클램프합니다. 클램프는 AgentRunner 내부, LLM 턴 직전, 트리거 출처가 해결된 직후에 실행됩니다. tier 4 도구는 자율 출처에 대해 레지스트리 게이트에서 항상 차단됩니다.
  • 컨텍스트 인식 자금 확인: 모든 자금 이동 도구 호출은 자금 확인 게이트를 거칩니다. 테스트 실행에서는 게이트가 MINARA_SKIP_FUND_CONFIRM 과 무관하게 2 단계 확인을 강제합니다. 테스트 실행이 조용히 자금을 움직이는 일은 없습니다.
  • 아카이브된 에이전트 fail-closed: 아카이브된 에이전트에 대한 수동 실행은 즉시 실패합니다. 아카이브된 에이전트의 cron 트리거가 세 번 연속 스킵되면 트리거가 자동으로 비활성화됩니다. 실행 중인 agent_turn 단계는 저장된 스냅샷에 대해 계속됩니다. 아카이브는 미래 방향의 작업입니다.
  • 스냅샷 격리: agent_id 로 에이전트를 참조하는 워크플로 인스턴스는 최초 실행 시 정의 전체를 스냅샷합니다. 소스 에이전트에 대한 후속 PATCH 나 ARCHIVE 는 어떤 실행 중 인스턴스에도 영향을 주지 않습니다.
  • 감사 로그: 각 실행은 요청된 위험 tier, 실효 (클램프된) 위험 tier, 트리거 출처, 떨어진 스킬 / 도구 목록을 감사 로그에 기록합니다. Web UI 는 History 탭에 표시하고, CLI 는 minara agents get <id> 뒤에 인스턴스 쿼리로 가져올 수 있습니다.

핸들러 계약은 Fund-Moving Confirm 을, 전체 감사 면은 Audit & Overrides 를 참조하십시오.

목차