Skip to content

LangChain / LangGraph / AutoGen — OpenAPI remote tool

ainote 의 OpenAPI 3.1 mirror 를 Python 에이전트 프레임워크에서 remote tool 로 등록한다. 별도 어댑터 코드 없이 openapi.json URL 만 있으면 된다.

LangChain

python
from langchain_community.tools.openapi.utils.openapi_utils import OpenAPISpec
from langchain.agents.agent_toolkits.openapi.toolkit import RequestsToolkit
from langchain.utilities.requests import RequestsWrapper

spec = OpenAPISpec.from_url("https://api.ainote.dev/api/mcp/openapi.json")

headers = {"Authorization": "McpKey <YOUR_MCP_KEY>"}
toolkit = RequestsToolkit(
    requests_wrapper=RequestsWrapper(headers=headers),
    allow_dangerous_requests=True,  # destructive 도구 (delete_task 등) 허용 시
)

# agent 에서 사용
from langchain.agents import create_openai_tools_agent
agent = create_openai_tools_agent(llm, toolkit.get_tools(), prompt)

destructive 도구

tool annotations.destructiveHint: true 인 도구 (delete_task, vault_sync, handoff_list 등) 는 allow_dangerous_requests=True 가 필수. production 환경에서는 explicit user consent 흐름을 추가 권장.

LangGraph (직접 tool wrapping)

LangGraph 에서 fine-grained control 이 필요하면 도구를 직접 wrap:

python
import requests
from langchain.tools import tool

AINOTE = "https://api.ainote.dev/api/mcp/tools"
HEADERS = {"Authorization": "McpKey <YOUR_MCP_KEY>"}

@tool
def handoff_save(project: str, topic: str, content: str, time: str = None) -> str:
    """Save a session handoff note. Use `time` (HHMM, KST) to disambiguate
    multiple handoffs on the same day."""
    body = {"project": project, "topic": topic, "content": content}
    if time:
        body["time"] = time
    r = requests.post(f"{AINOTE}/handoff_save", json=body, headers=HEADERS)
    return r.json()

@tool
def handoff_get(project: str, topic: str, date: str = None, time: str = None) -> str:
    """Retrieve a handoff. Omit date for latest matching."""
    body = {"project": project, "topic": topic}
    if date: body["date"] = date
    if time: body["time"] = time
    r = requests.post(f"{AINOTE}/handoff_get", json=body, headers=HEADERS)
    return r.json()

26 도구 전체를 미리 wrap 한 패키지를 contributing 환영 — langchain-ainote 또는 ainote-langchain 이름으로 PR 받습니다.

AutoGen

python
import autogen

ainote_tool_spec = {
    "url": "https://api.ainote.dev/api/mcp/openapi.json",
    "auth": {"type": "header", "name": "Authorization", "value": "McpKey <YOUR_KEY>"},
}

assistant = autogen.AssistantAgent(
    name="ainote_assistant",
    llm_config={"tools": [ainote_tool_spec]},
)

(AutoGen 의 정확한 tool spec 형식은 라이브러리 버전에 따라 다름 — 최신 docs 참조)

CrewAI

CrewAI 는 LangChain 호환이므로 위 LangChain 패턴 그대로 사용:

python
from crewai import Agent
from langchain_community.tools.openapi.utils.openapi_utils import OpenAPISpec

agent = Agent(
    role="Note keeper",
    goal="Manage user's notes and tasks via ainote",
    tools=[/* LangChain toolkit 결과 */],
)

도구 발견 (tools/list 등가물)

OpenAPI spec 의 paths 를 enumerate:

python
import requests
spec = requests.get("https://api.ainote.dev/api/mcp/openapi.json").json()

for path, ops in spec["paths"].items():
    op = ops["post"]
    name = path.split("/")[-1]
    annotations = op.get("x-mcp-annotations", {})
    print(f"{name}: {op['summary']}")
    print(f"  annotations: {annotations}")

26개 도구 + 각 annotations 출력.

안티패턴 — 피할 것

annotations 무시하고 모든 도구 자동 호출 — destructive 도구 (delete_task, vault_sync 등) 가 user consent 없이 실행되면 데이터 손실 가능

API key 하드코딩 — env var (AINOTE_API_KEY) 또는 secret manager 사용

rate limit 무시 — 짧은 시간 안 다수 호출 → 429. response 의 Retry-After 헤더 존중 (Phase 3 후 정식 도입 예정)

annotations 기반 게이팅 — destructive 도구는 user confirmation 후만 호출

idempotent 도구는 retry 안전 — 네트워크 오류 시 재시도해도 안전

다른 진영