| name | tool-creator |
| description | AnimaWorks용 Python 외부 도구 모듈을 만드는 메타 스킬. ExternalToolDispatcher·get_credential·permissions를 다룬다. Use when: core/tools에 모듈 추가, Web API 래퍼 구현, animaworks-tool로 호출할 커스텀 도구 개발이 필요할 때. |
tool-creator
개요
AnimaWorks의 도구는 3가지로 분류됩니다:
| 유형 | 배치 위치 | 탐색 방법 |
|---|
| 코어 도구 | core/tools/*.py | discover_core_tools() → TOOL_MODULES (시작 시 고정) |
| 공유 도구 | {data_dir}/common_tools/*.py | discover_common_tools() |
| 개인 도구 | {anima_dir}/tools/*.py | discover_personal_tools() |
{data_dir}은 통상 ~/.animaworks/입니다. 개인 및 공유 도구는 ExternalToolDispatcher가 refresh_tools로 재스캔하여 핫 리로드 가능합니다. ToolHandler는 write_memory_file로 tools/*.py에 쓸 때 permissions.json의 도구 생성 권한을 확인합니다.
개인 및 공유 도구는 Bash를 통해 animaworks-tool <도구> <서브커맨드> [인수]로 호출합니다. 스키마명 형식은 {tool_name}_{action} (예: my_tool + query → my_tool_query)입니다.
절차
Step 1: 도구 설계
- 도구명 결정 (스네이크 케이스, 예:
my_api_tool)
- 제공할 스키마(조작)를 정의
- 필요한 파라미터를 정의
Step 2: 모듈 파일 생성
아래 템플릿에 따라 Python 파일을 생성합니다.
단일 스키마 도구 (간단)
파일명 my_tool.py의 경우, animaworks-tool my_tool action [args]로 호출되어 스키마명 my_tool_action이 dispatch에 전달됩니다.
from __future__ import annotations
import logging
from typing import Any
logger = logging.getLogger("animaworks.tools")
def get_tool_schemas() -> list[dict]:
"""도구 스키마를 반환합니다 (필수)."""
return [
{
"name": "my_tool_action",
"description": "이 도구가 수행하는 작업 설명",
"input_schema": {
"type": "object",
"properties": {
"param1": {
"type": "string",
"description": "파라미터 설명",
},
"param2": {
"type": "integer",
"description": "선택 파라미터",
"default": 10,
},
},
"required": ["param1"],
},
}
]
def dispatch(name: str, args: dict[str, Any]) -> Any:
"""스키마명에 따른 처리를 실행합니다 (권장)."""
args.pop("anima_dir", None)
name == :
_do_action(
param1=args[],
param2=args.get(, ),
)
ValueError()
() -> [, ]:
{: }
다중 스키마 도구 (API 연동 등)
스키마명은 {tool_name}_{action} 형식입니다. animaworks-tool myapi query [args] 호출 시 myapi_query로 dispatch에 전달됩니다. 파일명: myapi.py.
from __future__ import annotations
import logging
from typing import Any
logger = logging.getLogger("animaworks.tools")
def get_tool_schemas() -> list[dict]:
return [
{
"name": "myapi_query",
"description": "API에 쿼리를 보내고 결과를 가져옵니다",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "검색 쿼리"},
"limit": {"type": "integer", "description": "최대 건수", "default": 10},
},
"required": ["query"],
},
},
{
"name": "myapi_post",
"description": "API에 데이터를 전송합니다",
"input_schema": {
"type": "object",
"properties": {
"data": {"type": "string", "description": "전송 데이터"},
},
"required": [],
},
},
]
:
() -> :
core.tools._base get_credential
._api_key = get_credential(
, , env_var=,
)
() -> []:
httpx
resp = httpx.get(
,
params={: query, : limit},
headers={: },
timeout=,
)
resp.raise_for_status()
resp.json()[]
() -> :
httpx
resp = httpx.post(
,
json={: data},
headers={: },
timeout=,
)
resp.raise_for_status()
resp.json()
() -> :
args.pop(, )
client = MyAPIClient()
name == :
client.query(
query=args[],
limit=args.get(, ),
)
name == :
client.post(data=args[])
ValueError()
Step 3: 파일 저장
개인 도구로 저장 (write_memory_file의 path는 anima_dir 기준 상대 경로):
write_memory_file(path="tools/my_tool.py", content=<코드>)
tools/에 쓰려면 permissions.json의 "도구 생성" 섹션에서 개인 도구 허가가 필요합니다.
Step 4: 도구 활성화
저장 후 refresh_tools를 호출하여 핫 리로드합니다:
refresh_tools()
세션을 재시작하지 않아도 즉시 도구를 사용할 수 있습니다. 개인 도구는 permissions.json의 외부 도구 섹션에 등록할 필요가 없으며, refresh_tools로 탐색되면 Bash + animaworks-tool <도구> <서브커맨드>로 호출 가능합니다.
Step 5: 공유 (선택)
다른 Anima도 사용하게 하려면 도구를 공유합니다:
share_tool(tool_name="my_tool")
이렇게 하면 ~/.animaworks/common_tools/에 복사되어 모든 Anima에서 사용 가능해집니다. 공유에는 permissions.json에서 공유 도구 허가가 필요합니다.
필수 인터페이스
| 함수 | 필수 | 설명 |
|---|
get_tool_schemas() | 필수 | 도구 스키마 목록을 반환. name, description, input_schema (또는 parameters) 포함 필요 |
dispatch(name, args) | 권장 | 스키마명에 따른 디스패치. ExternalToolDispatcher가 우선 호출. args에서 args.pop("anima_dir", None)으로 제거 필요 |
| 스키마명과 동명의 함수 | 대안 | dispatch() 대신 사용 가능 |
cli_main(argv) | 선택 | animaworks-tool <tool_name>으로 단독 실행용 |
EXECUTION_PROFILE | 선택 | 장시간 실행 도구용. animaworks-tool submit으로 백그라운드 투입 가능 |
Bash 호출
Anima는 Bash를 통해 animaworks-tool <도구> <서브커맨드> [인수]로 개인/공유 도구를 호출합니다:
animaworks-tool myapi query "검색어" [--limit 10]
schema_name = tool_name + "_" + action이 dispatch(name, args)에 전달됩니다. 위 예시에서 name="myapi_query"입니다.
스키마 정의 규약
input_schema와 parameters 모두 지원되며 core/tooling/schemas._normalise_schema에서 정규화됩니다.
{
"name": "tool_action_name",
"description": "1~2문장 설명",
"input_schema": {
"type": "object",
"properties": { ... },
"required": [ ... ],
},
}
인증 정보 취득 (get_credential)
API 키 등은 get_credential()을 통해 취득합니다. 하드코딩하지 마세요.
from core.tools._base import get_credential
api_key = get_credential(
credential_name="myapi",
tool_name="myapi_tool",
key_name="api_key",
env_var="MYAPI_KEY",
)
해석 순서: config.json → vault.json (암호화 볼트) → shared/credentials.json → 환경변수. 어디에도 없으면 ToolConfigError.
permissions.json의 도구 생성 허가
도구 생성 및 공유를 위해 permissions.json에 다음을 추가합니다:
## 도구 생성
- 개인 도구: yes
- 공유 도구: yes
yes 대신 OK, enabled, true도 유효합니다.
검증 체크리스트
보안 가이드라인
-
인증 정보: get_credential()을 통해 취득. 하드코딩 금지
-
접근 제한: 다른 Anima의 디렉토리에 접근하지 않음
-
타임아웃: 외부 API에 반드시 타임아웃 설정 (권장: 30초)
-
로깅: logging.getLogger("animaworks.tools") 사용
-
의존성: 외부 라이브러리는 함수 내에서 임포트 (지연 임포트)
주의사항
- 도구는 Python 코드이므로 스킬(Markdown 절차서)과 다릅니다
- 도구 생성에는 permissions.json의 "도구 생성" 섹션에서 개인 도구: yes 허가가 필요합니다
- 공유 도구화에는 공유 도구: yes 허가가 필요합니다
- 생성한 도구는
refresh_tools 호출로 즉시 탐색됩니다 (핫 리로드)
- 개인/공유 도구는 permissions.json의 "외부 도구" 섹션에 등록 불필요.
refresh_tools로 탐색되면 Bash + animaworks-tool에서 사용 가능
- 스키마명은
{tool_name}_{action} 형식. 다른 도구와 충돌하지 않도록 고유하게 유지하세요
- 코어 도구와 동명의 개인/공유 도구는 섀도잉되어 건너뛰어집니다 (
core/tools/__init__.py)