짜는 법과 돌리는 법을 답하는 묶음입니다. 무엇을 부를 수 있는지(Zio.node · Zio.text · Zio.utils …)는 주제별 문서에 따로 있고, 여기서 다루는 것은 그 함수를 어디에 놓고 어떻게 돌리는가입니다. 어느 것을 쓰든 놓는 자리와 돌리는 길은 같습니다.
플랫폼의 .skills/ 디렉토리 안에 파이썬 스크립트를 작성하고 @zio_skill 데코레이터를 붙이면, 해당 함수는 skillFunction 노드이자 AI 도구로 등록됩니다. 플랫폼 전체를 내렸다 올릴 필요는 없습니다 — 그 스킬 하나만 다시 띄우면 됩니다(아래 「다시 띄우기」).
main.py는 작성할 필요 없습니다!
@zio_skill 함수만 작성하면, 플랫폼이 콜드 스타트 시 자동으로 main.py를 생성하고 가상환경(.venv)도 만듭니다. 둘 다 직접 만들지 마십시오.
.skills/ 아래에 폴더를 하나 만들고, 그 안의 .py 파일에 @zio_skill 함수를 적으면 끝입니다. 폴더 하나가 배포 단위 하나(가상환경 하나)입니다.
.skills/
└── <폴더명>/ ← 배포 단위 하나
├── <아무이름>.py ← @zio_skill 함수를 여기 적는다 (여러 개 가능)
├── requirements.txt ← (선택) 추가 라이브러리
├── main.py ← ⚡ 플랫폼 자동 생성. 직접 만들지 말 것
└── .venv/ ← ⚡ 플랫폼 자동 생성. 직접 만들지 말 것
requirements.txt 는 가상환경을 처음 만들 때 한 번만 읽습니다. (pandas · fastapi · uvicorn · requests 는 적지 않아도 깔립니다.) 나중에 한 줄 더해도 저절로 깔리지 않습니다 — 그때 무엇을 해야 하는지는 아래 「라이브러리를 나중에 더했다면」 에 있습니다.
.skills/ 바로 밑에 놓은 낱개 .py 는 스킬이 아닙니다. 폴더가 있어야 플랫폼이 그 안에 main.py 와 가상환경(.venv)을 만들고, SDK 경로를 꽂아 프로세스를 띄웁니다.
폴더 없이 그냥 실행하면 ModuleNotFoundError: No module named 'zio_ontology' 가 납니다. 코드가 틀린 것이 아니라 띄워 주는 절차를 안 거친 것입니다. 폴더로 옮기면 그대로 돕니다.
SSH 컨테이너에는 파이썬이 깔려 있지 않습니다.python --version 도 import zio_ontology 도 여기서는 안 됩니다 — 없는 것이 정상이니 알아볼 필요가 없습니다. 여기는 코드를 적는 자리이고, 코드가 도는 곳은 스킬 러너 컨테이너입니다. 파이썬도, 가상환경도, zio_ontology 모듈도 전부 그쪽에 있습니다.
폴더로 두면 부르는 길이 셋 생깁니다. 셋 다 같은 함수를 부릅니다 — 어느 길로 부르든 결과가 같습니다.
주소는 하나뿐입니다. 포트로는 못 부릅니다
스킬은 스킬 러너라는 또 다른 컨테이너에서 돕니다. SSH 로 붙은 자리에서는 그 컨테이너가 아예 안 보입니다 — localhost 도, api:<포트> 도 안 열립니다. 포트 번호를 주소에 쓰지 마십시오. 어디에서 봤든 그것은 러너 안에서만 뜻이 있는 번호입니다.
어디서 부르나
주소
내 노트북 브라우저
플랫폼 주소 그대로 — https://<플랫폼 주소>/skills/<폴더명>/docs
SSH 안(터미널·IDE의 AI)
http://api:8000/api/artifacts/skills/call/<폴더명>/execute/<함수명>— 늘 이 주소입니다. 바깥 주소(https://…)로는 못 나갑니다.
부르는 길
언제 쓰나
/skills/<폴더명>/docs
브라우저로 열면 함수 목록이 나오고 눌러서 바로 실행됩니다(Swagger). 표 하나 만들기 같은 한 번짜리 작업은 이 길이 제일 빠릅니다. 좌측 스킬 탭에서도 열 수 있습니다.
POST /execute/<함수명>
curl 이나 다른 프로그램에서 부를 때. 인자는 JSON 본문의 최상위 열쇠로 찾아 넣습니다 — 함수의 인자 이름과 열쇠 이름이 같으면 됩니다. 브라우저 쪽에서는 앞에 /skills/<폴더명> 이 붙고, SSH 안에서는 앞에 http://api:8000/api/artifacts/skills/call/<폴더명> 이 붙습니다(아래).
skillFunction 노드
에이전트 빌더에서 폴더명/함수명 을 적어 워크플로우에 끼울 때. 배치와 디버거가 지나는 길이 이것입니다.
SSH 로 붙은 이 자리에는 **python·python3·pip 이 없습니다.**코드를 쓰는 곳과 도는 곳이 다릅니다 — 당신은 파일만 쓰고, 실행은 다른 컨테이너가 합니다. 그래서 아래가 python main.py 가 아니라 curl 한 줄입니다.
헷갈리기 쉬운 자리가 둘 있습니다. .venv/ 폴더가 보이지만 그 안의 python 은 다른 컨테이너를 가리키는 끊어진 링크이고, main.py 맨 아래의 if __name__ == "__main__": uvicorn.run(...) 도 여기서 부르라는 뜻이 아닙니다 — 러너가 그 파일을 그렇게 띄웁니다. apt install python3 같은 것을 시도하지 마십시오. 필요 없는 일이고 되지도 않습니다.
고친 뒤에는 다시 띄워야 합니다. 스킬은 한 번 뜨면 그 상태로 계속 돌고, 파일이 바뀌어도 저절로 다시 읽지 않습니다.
다만 이것은 파이썬 코드(.py) 얘기입니다.index.html·CSS·JS 같은 정적 파일은 요청마다 디스크에서 새로 읽어 보내므로, 다시 띄울 필요 없이 브라우저 새로고침이면 바뀝니다. 화면(프론트)만 손봤다면 restart 를 부르지 마십시오 — 부를 함수의 파이썬을 고쳤을 때만 다시 띄웁니다.
거꾸로, 안 고쳤으면 다시 띄우지 마십시오.restart 는 떠 있는 것을 죽이고 새로 띄웁니다 — 함수를 부를 때마다 붙이면 그때마다 프로세스가 갈려 느려질 뿐입니다. 주소는 그대로이니 그냥 부르면 됩니다.
SSH 안에서 — 위 「돌려 보기」의 restart 줄입니다. 떠 있으면 죽이고 새로 띄웁니다.
웹 화면에서 — 좌측 스킬 탭에서 그 스킬을 재시작합니다.
브라우저로 /skills/<폴더명>/docs 를 여는 것은 재시작이 아닙니다. 안 떠 있을 때만 띄우고, 돌고 있으면 옛 코드가 그대로 응답합니다.
뜨다가 실패하면 그 폴더의 .skill_stderr.log 에 이유가 적힙니다. SSH 안에서는 이렇게 봅니다.
curl -s "http://api:8000/api/artifacts/skills/logs?skill_name=<폴더명>"
떴다고 내 함수가 등록된 것은 아닙니다. 문법 에러는 위처럼 재시작 자체가 실패하지만, @zio_skill 을 안 붙였거나 함수 이름에 오타가 있으면 프로세스는 멀쩡히 뜨고 부를 때서야 404 가 납니다. 그래서 재시작 응답에 지금 등록된 함수 목록(loaded_functions, 이름·시그니처·설명 첫 줄)을 함께 돌려줍니다 — 내가 부르려는 이름이 거기 있는지 먼저 보십시오. 하나도 없으면 warning 이 왜 비었는지 알려 줍니다. (_ 나 main 으로 시작하는 파일은 안 읽습니다.)