Zio.Tools
메일 발송·평판 조회·파일 다운로드처럼 화면에 등록된 도구를 스킬 안에서 부릅니다. 스킬은 /tools/ 를 직접 부를 수 없습니다 — 스킬이 도는 자리에서 그 길은 막혀 있고, 데이터에 닿는 문은 SDK 하나뿐입니다. Zio.tools 가 그 문을 지나 대신 부릅니다. 신분증을 보이고, 부를 수 있는 도구만(allowlist) 통과합니다.
실패를 삼키지 마십시오. 도구가 실패하면 이 함수는 예외를 던집니다 — 그대로 올려 스킬이 실패로 끝나게 하십시오. 전에는
/tools/를 직접 부르다 막힌 실패를try/except로 삼켜 **「거짓 성공」**을 냈고, 그러면 결과가 저장 안 된 채로 노드가 성공으로 남았습니다.어느 도구를 어떤 인자로 부르는지는 그 도구의 규격을 따릅니다 — 에이전트 빌더의 도구 목록에서 확인하십시오. 스킬 안에서 쓸 수 있는 것은
Zio.tools.list()로 봅니다.
from zio_ontology import Zio
# 스킬에서 부를 수 있는 도구 목록for t in Zio.tools.list(): print(t["tool_id"], t["method"])
# 메일 발송 (인자는 그 도구의 규격을 따른다)Zio.tools.execute("send_email_via_smtp", { "to_email": "hong@example.com", "subject": "주간 업무 확인 요청", "body": "<p>확인 부탁드립니다.</p>", # 본문은 이미 완성된 것을 넘긴다})
# 도메인 평판 조회 — 결과(dict)를 그대로 돌려받는다whois = Zio.tools.execute("analyze_domain", {"domain_name": "example.com"})print(whois.get("is_registered"), whois.get("domain_age_days"))
# 파일 다운로드 — 바이너리는 bytes 로 온다pdf_bytes = Zio.tools.execute("gdrive_download_file", {"file_id": "1AbC..."})open("/tmp/spec.pdf", "wb").write(pdf_bytes)| Method | Description |
|---|---|
Zio.tools.list() |
스킬에서 부를 수 있는 도구 목록. [{tool_id, method}]. 여기 없는 도구는 부를 수 없습니다 — 셸·파일·raw 쿼리 같은 원시 도구는 스킬에 열려 있지 않습니다. |
Zio.tools.execute(tool_id, args) |
도구 하나를 부릅니다. tool_id 는 도구 이름, args 는 그 도구가 받는 인자(dict). 성공하면 도구가 준 결과(대개 dict)를, 파일 다운로드 같은 바이너리는 bytes 를 돌려줍니다. |
부를 수 없는 도구는 안내와 함께 막힙니다
섹션 제목: “부를 수 없는 도구는 안내와 함께 막힙니다”허용 목록에 없는
tool_id는PermissionError로 막히고, 부를 수 있는 도구 목록을 문장에 담아 줍니다. 셸 실행·파일 읽기/쓰기·raw 쿼리는 스킬에서 부를 수 없습니다 — 필요한 일이 있으면 그 길은 SDK 에 제대로 된 문으로 냅니다./tools/를 손으로 부르지 마십시오.
도구가 하는 일과 스킬이 하는 일은 다릅니다
섹션 제목: “도구가 하는 일과 스킬이 하는 일은 다릅니다”
Zio.tools는 이미 등록된 도구를 부르는 창구입니다. 데이터를 읽고 쓰는 일은 도구가 아니라Zio.code·Zio.node·Zio.entity·Zio.ingestion으로 합니다 — 그쪽이 스킬이 데이터에 닿는 정식 문입니다.
도구 만들기 — 바깥 REST API·원격 MCP 등록
섹션 제목: “도구 만들기 — 바깥 REST API·원격 MCP 등록”필요한 도구가 없으면 직접 만듭니다. 두 가지를 등록할 수 있습니다: 바깥의 REST API(Postman 처럼 “이 주소를 이렇게 부른다”), 그리고 원격 MCP 서버(DeepWiki·Context7 처럼 URL 로 붙는 MCP). 등록해 두면 에이전트의 모델이 스스로 호출합니다(LLM tool calling) — REST 는 params 규격대로 인자를, MCP 는 action 과 인자를 채웁니다.
v1 은
restapi와원격 HTTP MCP를 만듭니다. 로컬 stdio MCP·skill 은 프로세스를 띄우는 경계라 아직 웹 관리자 전용이고, custom_script 는 미구현입니다.만든 도구는 초안으로 태어납니다(
useYN='N') — 사람이 웹 도구 빌더(ToolBuilder) 에서 프리뷰로 확인하고 켭니다. 도구는 인스턴스 전체가 공유하므로 이 검토 관문이 중요합니다.보안: 여러분이 만든 도구의 실제 호출은 격리된 자리(skillnet)에서 나갑니다 — 그래서 바깥 주소에는 닿지만 내부(neo4j·redis 등)에는 못 닿습니다.
url에 내부 주소를 적어도 동작하지 않습니다(그렇게 설계했습니다).
from zio_ontology import Zio
# 바깥 REST API 를 도구로 등록 (초안으로 생성)got = Zio.tools.create( title="날씨 조회", url="https://api.weather.com/v1/current?city={{city}}", method="GET", headers={"X-API-Key": "..."}, params=[ {"key": "city", "type": "string", "required": True, "description": "조회할 도시명"}, ])print(got["id"], got["tool_id"]) # -> 53 weather_...print(got["warnings"]) # 이상하면 여기 담긴다 — 꼭 읽는다
# 한 도구의 전체 설정 보기 (id 또는 tool_id 로)Zio.tools.get(got["tool_id"])
# 고치기 (안 준 것은 유지, tool_id 는 안 바뀐다)Zio.tools.update(got["id"], description="도시별 현재 날씨")
# ── 원격 MCP 서버 등록 (DeepWiki·Context7 처럼 URL 로 붙는 MCP) ──mcp = Zio.tools.create( title="내 위키", type="mcp", url="https://mcp.deepwiki.com/mcp", # 원격 HTTP MCP 서버 주소 transport="http") # "http"(Streamable) 또는 "sse"# 모델은 실행 시 action_name(예: ask_question) + JSON 인자로 호출합니다.# 로컬 실행(command 방식) MCP 는 SDK 로 못 만듭니다 — 원격 HTTP MCP 만.
# 지우기 (사용자가 만든 것만 — 시스템 도구는 거부)Zio.tools.delete(got["id"])
# 이제 웹 도구 빌더에서 열어 프리뷰 → 활성화(켜기)| Method | Description |
|---|---|
Zio.tools.create(title, url, ...) |
도구를 등록합니다(초안). restapi(기본): method·headers·auth· params·body·response_schema, params 가 LLM 입력 계약 ({key,type,required,description,default}), {{var}} 자동 인자화. mcp(type="mcp"): url·transport(http/sse) — 원격 HTTP MCP 만(로컬 stdio 는 웹 관리자 전용). {id, tool_id, warnings} 반환. |
Zio.tools.get(ref) |
한 도구의 전체 설정(입력 params·인증·바디 등). ref 는 id 또는 tool_id. |
Zio.tools.update(ref, ...) |
기존 사용자 도구의 설정을 교체합니다. 안 준 것은 유지, tool_id(이름)는 불변. 시스템 도구는 거부. |
Zio.tools.delete(ref) |
사용자 도구를 지웁니다(시스템 도구는 거부). |
시스템 도구 vs 내 도구
섹션 제목: “시스템 도구 vs 내 도구”전체 사용자에게 기본 제공되는 시스템 도구는 SDK 로 만들거나 고칠 수 없습니다 (읽기·부르기만).
create로 만드는 것은 내(사용자) 도구이고,update·delete도 내 도구에만 됩니다. 목록은Zio.tools.list()로 봅니다.