app-ai-wiring
Skill11 starsChanged 3 months agoApache-2.0View on GitHub
앱(웹·서버·스크립트 등)에 AI/LLM 을 연결할 때 사용. tiguclaw 에 붙이는 두 방식 — (A) tiguclaw 직결 커스텀 엔드포인트(비서의 도구·스킬·메모리까지 쓰는 에이전틱 호출, 규약 자유) vs (B) OpenAI 호환 LLM 게이트웨이(OpenRouter·OpenAI 와 baseURL 만 바꿔 스왑 가능한 표준 규약) — 의 선택 기준·규약·배선 절차·검증을 담는다. 트리거: '앱에 AI 붙여줘', '이 앱에서 LLM 쓰게 해줘', 'tiguclaw 를 백엔드로', '오픈라우터처럼 연결', 'API 로 비서 호출', '게이트웨이 켜줘', 앱 개발 중 LLM 연결 지점에 도달했을 때. 사용자가 방식을 안 정했으면 §1 기준으로 추천하고 확인받은 뒤 배선한다.
- Reads credentials
In this repository13 other files it gives its agents.
- claude-wrapper-syncSkill
- code-reviewSkill
- codex-wrapper-syncSkill
- db-maintenanceSkill
- feedback-captureSkill
- harnessSkill
- incident-responseSkill
- memory-tidySkill
- plugin-creatorSkill
- project-commandsSkill
- skill-creatorSkill
- tiguclaw-bug-reportSkill
- verifySkill
The file
Files
앱 ↔ AI 연결 배선 (tiguclaw)
앱에 AI 를 붙이는 방법은 두 가지다. 성격이 완전히 달라 먼저 고르고 배선한다. 사용자가 지정했으면 그대로 따르고, 안 정했으면 §1 로 추천 + 확인받는다(맘대로 정하지 말 것).
§1 어느 쪽인가 — 판단 기준
| A. tiguclaw 직결 엔드포인트 | B. OpenAI 호환 게이트웨이 | |
| 앱이 얻는 것 | 비서 자체(도구·스킬·메모리·서브에이전트·프로젝트 맥락) | LLM 한 방(순수 텍스트 생성) |
| 규약 | 없음 — 내가 자유 설계 | OpenAI 스펙 고정 |
| 교체 | tiguclaw 전용(스왑 불가) | OpenRouter·OpenAI 로 baseURL 만 바꿔 스왑 |
| 반영 | 재시작 불요(데이터 기반) | 토큰 설정 시 재시작 필요(.env) |
A 를 고르는 신호: "내 파일 읽어서", "메모리 참고해서", "스킬 태워서", "프로젝트 맥락 알고", 여러 단계 자율 작업, tiguclaw 만의 능력이 핵심일 때. B 를 고르는 신호: 요약·분류·번역·챗봇 등 모델만 있으면 되는 일, 나중에 상용 API 로 갈아탈 계획, 이미 OpenAI SDK 로 짠 앱, 함수호출/비전 같은 표준 기능이 필요할 때.
애매하면 B(표준이라 나중에 A 로 못 바꾸는 손해가 없고, 스왑 자유). 단 "비서를 부르고 싶은 것"이면 B 로는 절대 안 되니 A.
§2 모드 A — tiguclaw 직결 커스텀 엔드포인트
엔드포인트 = 슬래시 명령의 HTTP 판. <home>/endpoints/<name>.md(frontmatter + 프롬프트
템플릿)를 http-bridge 가 매 요청 발견해 서빙한다. 임의 코드 0 = 데이터만, 재시작 불요.
배선
register_endpoint도구로 등록(list_endpoints/delete_endpoint로 조회·삭제).path— 라우트(예/weather). 슬래시 시작·소문자 정규화.method—GET|POST(기본 POST).role— 인증 게이트(기본write). 앱은 bridge 토큰으로 호출.mode— 기본restricted(도구 0). 비서 도구가 필요하면 명시적으로 열어야 함.- 본문 = 프롬프트 템플릿(요청 파라미터를 끼워 넣음).
- 앱은 그 경로를 호출:
POST http://127.0.0.1:<HTTP_BRIDGE_PORT>/<path>+ bridge 토큰.
동기 / 스트리밍
엔드포인트도 둘 다 된다 — 앱이 고른다.
- 동기(기본): 그냥 POST →
{ "result": "<본문>" }한 번에. 앱 코드 2줄. - 스트리밍: body 에
"stream": true(또는?stream=1) → SSE.
★앱은 result/error 를 받았는지로 성패를 판정할 것(연결만 끊긴 것과 구분). ★data: {"type":"delta","text":"…"} 진행 조각(0회 이상) data: {"type":"result","result":"…"} 최종(성공 시 1회) data: {"type":"error","error":"…"} 실패(1회) data: [DONE] 종료 표식EventSource는 POST 불가 →fetch+ReadableStream으로 읽는다. - 타임아웃: 엔드포인트 전용
ENDPOINT_TIMEOUT_MS(기본 5분, env 조정). 폴백 낀 긴 턴(70초)이 504로 잘리던 실사고 때문에 분리·상향했다. 스트리밍이면 데이터가 흘러 중간 계층(프록시·Tailscale) idle timeout 도 회피된다.
주의
- 기본이
restricted(도구 0)라 에이전틱 능력을 쓰려면 mode 를 열어야 한다. 열 때는 무인 트리거라는 점을 감안해 위험 도구 노출을 최소화(사용자 확인). - 응답 규약은 내가 정한다 = 앱과 계약을 명시해 둘 것(문서/주석).
§3 모드 B — OpenAI 호환 LLM 게이트웨이 (규약)
POST /v1/chat/completions · GET /v1/models 를 OpenAI 규격 그대로 서빙한다.
OpenRouter 와 같은 규약이라 앱은 baseURL·apiKey만 바꾸면 그대로 붙는다.
켜는 법 (기본은 꺼져 있음 = 404)
① 토큰(시크릿) — <home>/.env, 최초 1회만 · 재시작 필요
LLM_GATEWAY_TOKEN=<임의 비밀문자열>시크릿이라 파일(settings.json)에 raw 로 두지 않는다. env 는 부팅 고정이라
이 값을 새로 넣거나 바꿀 때만 재시작(tiguclaw restart).
② 나머지 설정 — <home>/settings.json, ★재시작 불요(매 요청 fresh read)
{
"gateway": {
"enabled": true,
"models": ["codex:gpt-5.5"],
"maxConcurrency": 4,
"tokenEnv": "LLM_GATEWAY_TOKEN"
}
}enabled— 킬스위치(토큰은 둔 채 껐다 켰다). 생략=true.models— 기본 모델 풀. 생략 시 envLLM_GATEWAY_MODELS, 그것도 없으면 기본 모델 프로파일.maxConcurrency— 동시 처리 상한(초과 429). 생략=4.tokenEnv— 토큰을 읽을 env 변수명. 생략=LLM_GATEWAY_TOKEN.- ★
gateway섹션 자체가 없으면 레거시 env 경로(토큰 존재만으로 활성).
→ 토큰만 한 번 심어두면, 그 뒤 켜기/끄기·모델·동시성 변경은 재시작 없이 즉시 반영된다. 즉 비서가 사용자 대화를 끊지 않고 게이트웨이를 토글할 수 있다.
주소 = http://127.0.0.1:<HTTP_BRIDGE_PORT>/v1 (기본 127.0.0.1 바인드 = 로컬 전용).
앱 배선 (OpenAI SDK — OpenRouter 자리에 그대로)
const client = new OpenAI({
baseURL: process.env.OPENAI_BASE_URL, // http://127.0.0.1:<port>/v1
apiKey: process.env.OPENAI_API_KEY, // = LLM_GATEWAY_TOKEN
});모델 이름 규약 (★OpenRouter 슬러그와 다름)
provider:model—anthropic:claude-sonnet-5,codex:gpt-5.6-terra,openai:gpt-4o-mini,ollama:qwen2.5:7b(settings.jsonmodels.providers에 정의한 이름)tier:<프로파일>— settings.jsonmodels.profiles의 명명 프로파일(tier:high·tier:default등)- 목록은
GET /v1/models로 확인(거기 나온 id 를 그대로 쓰면 왕복 보장) - ⚠️ 목록에 없는 이름을 보내면 400 이 아니라 조용히 기본 풀로 폴백한다(알려진 갭) —
반드시
/v1/models의 id 를 쓸 것.
지원 범위
되는 것: 채팅 · 스트리밍(SSE, stream:true — OpenAI SDK 가 파싱까지 처리하므로 앱
부담 거의 0. 엔드포인트 스트리밍은 직접 파싱해야 하는 것과 대비되는 장점) ·
함수호출(tools/tool_calls) · 비전(이미지 입력) · usage 토큰 · /v1/models
- 함수호출: 앱이
tools를 주면 모델이 실행하지 않고tool_calls를 반환 (finish_reason:"tool_calls") → 앱이 실행하고role:"tool"로 결과를 돌려주면 이어감. ★세 어댑터 전부(claude·codex·openai)에서 되고, 구독 인증만으로도 된다(API 키 불요). 200 으로 받아 "모델이 도구를 안 쓴다"로만 보였다. 그때 배운 것: 되는지 물어보지 말고 §5 검증을 돌려라. tool_choice—"none"은 스키마를 아예 안 넘겨 집행하고,"required"를 못 지키면 에러(tool_choice_unsatisfied)로 알린다. 텍스트를 성공인 척 주지 않는다.- ★빈 응답은 없다. 텍스트도 함수콜도 없으면 200 이 아니라
empty_completion에러다 (응답은 셋 중 하나:tool_calls· 텍스트 · 명시적 에러). - 비전:
image_url의data:URI(base64)만 지원.http(s)URL 은 미지원(SSRF 방지).
안 되는 것: 이미지·음성 생성(/v1/images·/v1/audio) · /v1/completions(legacy) ·
embeddings · response_format 스키마 강제.
→ 이미지/음성 생성이 필요하면 그 모달리티만 실제 프로바이더(OpenAI·Replicate 등)로 직접 붙인다.
멀티라운드 한계(정직하게)
게이트웨이는 요청마다 새 세션이라, 이전 tool_calls/role:"tool" 은 텍스트로 재구성해
모델에 전달한다(네이티브 tool-state 재현이 아님). 단순 왕복엔 충분하나, 복잡한 다단계 함수
호출 루프는 기대만큼 안 이어질 수 있다.
§4 dev ↔ prod 스위처블 배선 (기본 권장)
두 모드 다 OpenAI 호환이라 코드 수정 0으로 전환된다. 앱엔 항상 env 두 벌을 준비:
# dev — tiguclaw 게이트웨이(무료·로컬)
OPENAI_BASE_URL=http://127.0.0.1:17011/v1 # HTTP_BRIDGE_PORT (기본 17011)
OPENAI_API_KEY=<LLM_GATEWAY_TOKEN>
OPENAI_MODEL=codex:gpt-5.5
# prod — 상용 API / OpenRouter
OPENAI_BASE_URL=https://openrouter.ai/api/v1
OPENAI_API_KEY=sk-or-...
OPENAI_MODEL=anthropic/claude-sonnet-4.6모델 이름이 규약별로 다르므로 모델명도 env 로 뽑아둘 것.
비서 인격·기억은 실리지 않는다
게이트웨이 턴은 격리 작업폴더에서 돌아 tiguclaw 의 AGENT.md·SYSTEM.md·메모리가 안
실린다. 앱이 준 system 이 곧 시스템 프롬프트다(안 주면 빈 값).
- ★잔여(막을 수 없음): 구독 OAuth 계정 이메일은 SDK 가 스스로 싣는다(
~/.claude.jsonoauthAccount). 우리 프롬프트·설정엔 없다. 완전 차단은 상용 API 키 경로뿐 — 아래 약관 가드와 같은 결론으로 이어진다.
★약관 가드 (중요)
tiguclaw 는 개인 구독 인증(Claude Code OAuth·ChatGPT)으로 돌 수 있다. 이 백엔드를 외부 앱·타인에게 중계·판매하면 약관 위반 소지가 크다.
- 본인 로컬 dev/테스트 → 게이트웨이 OK
- 외부 배포·타인 사용·부하 테스트 → 반드시 상용 API 키(
LLM_GATEWAY_MODELS를 상용 프로바이더로 두거나, 앱을 OpenRouter/OpenAI 로 직결)
네트워크 노출 시
기본 127.0.0.1. 다른 기기에서 붙이려면 HTTP_BRIDGE_HOST=0.0.0.0 — 단 TLS 없음이라
Tailscale 같은 암호화 경로 권장, 그리고 그 포트엔 대시보드·제어 API 도 함께 열리므로
프록시로 /v1/* 만 통과시키는 게 안전.
★이름으로 붙이면 HTTP_BRIDGE_ALLOWED_HOSTS 도 필요하다 (DNS 리바인딩 방어). IP 로
붙으면 설정 불요 — 리바인딩은 이름이 있어야 성립하므로 IP 리터럴은 그냥 통과한다.
안 적어서 막히면 403 본문이 적을 값을 알려준다.
§5 배선 후 검증 (반드시)
# 게이트웨이(모드 B)
curl -H "Authorization: Bearer <TOKEN>" http://127.0.0.1:<port>/v1/models
curl http://127.0.0.1:<port>/v1/chat/completions \
-H "Authorization: Bearer <TOKEN>" -H "Content-Type: application/json" \
-d '{"model":"<위 목록의 id>","messages":[{"role":"user","content":"안녕"}]}'- 함수호출을 쓰는 앱이면
tools를 실어finish_reason:"tool_calls"가 오는지까지 확인. - 모드 A 면 등록한 경로를 bridge 토큰으로 호출해 실제 응답을 확인.
- 앱에서 한 번 실제로 호출해 보고 보고할 것(추측 금지).
불변식
- 사용자가 모드를 정했으면 그대로. 안 정했으면 §1 로 추천 후 확인.
- 게이트웨이 토큰·상용 키는 절대 코드·settings.json 에 raw 로 두지 말 것(env 만).
- 토큰을 새로 심을 때만 재시작이 필요하다 — 라이브 데몬이 대화 중일 수 있으니 사전 고지. 그 외(켜기/끄기·모델·동시성)는 settings.json 편집으로 재시작 없이 처리한다.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

