오픈소스 · MIT · Python 3.12 이상
에이전트가 사용하는 API가 바뀌는 시점을 파악한다.
Tiltmeter는 실제 응답을 바탕으로 의존 중인 각 서드파티 API의 형태를 학습한다. API가 바뀌면 사용자와 CI, 에이전트에 알리고 코드 수정 풀 리퀘스트를 연다.
pip install tiltmeter
에이전트는 /llms.txt를 읽고 직접 설정할 수 있다.
종료된 API가 운영 코드에 남아 있다
2026년 10월 현장 보고서에서 Tiltmeter는 이미 배포된 API 변경을 대상으로 공개 GitHub 코드를 검색했다. 별을 많이 받은 활성 저장소부터 골라 Tiltmeter가 수정한 풀 리퀘스트를 열고, 각 변경을 사람이 검토하도록 했다. 모든 풀 리퀘스트와 상태
- Groq가 무료 및 개발자 키에서
llama-3.3-70b-versatile을 종료한 지 10주가 지났지만, 이 모델 이름을 포함한 파일이 GitHub에 31만4천 개 남아 있다. - Tiltmeter는 8개 API 변경에 대해 풀 리퀘스트 64개를 열었고, 그중 5개가 병합됐다. 모두 Tiltmeter가 작성한 변경이다.
- 수정된 저장소의 GitHub 별 수는 합계 100만 개 이상이다.
Groq의 경우 인기 있고 활발한 AI 저장소 1,619개 가운데 260개가 Groq에서 종료한 모델을 여전히 지정하며, 이 모델이 기본값인 경우도 많다. LibreChat, 하버드의 Machine Learning Systems 책, DB-GPT 등에서 수정 15건이 나왔다. Groq 관련 변경
Anthropic API는 모델 ID만 바꾸면 해결되지 않는다. 권장 대체 모델인 Claude Sonnet 5.5는 temperature와 thinking budget을 거부한다. 유지관리자 두 명이 초기 수정안에서 이 문제를 발견한 뒤 Tiltmeter는 요청을 구성하는 방식도 조정하도록 바꿨다. Anthropic 관련 변경
Stripe의 API 버전 2025-03-31에서 제거된 subscription.current_period_end를 여전히 읽는 저장소가 78개다. 여기에는 Stripe의 구독 예제도 포함된다. 이 예제는 이제 Stripe SDK의 타입 검사에 통과하지 않는다. Stripe 관련 변경
Slack의 files.upload는 2025년 11월 12일 중단됐지만 openreplay, reconftw, intuit/auto는 여전히 이 기능을 호출했다. 수정안은 이를 대체한 3단계 업로드 절차를 사용한다. openreplay의 수정
OpenWeatherMap One Call API 2.5는 2024년 6월 종료됐다. 별 2만1천 개를 받은 Aerial, Raycast의 스크립트 명령, Linux Mint의 날씨 애플릿은 여전히 이 API를 호출했다. Aerial의 수정
HubSpot Pipelines API v1은 2026년 12월 4일 중단될 예정이다. Airbyte의 HubSpot 커넥터는 아직 이 API를 읽고 있다. 이는 종료 뒤가 아니라 종료 전에 코드를 고치는 사례다.
실제 응답을 비교해 API 변경을 알린다
Tiltmeter의 예시에서는 billing_customers 엔드포인트의 GET /v1/customers 응답을 기준선과 비교한다. balance가 정수에서 문자열로 바뀌고, 항상 존재하던 phone이 사라졌으며 phone_number가 새로 나타났다. Tiltmeter는 phone이 phone_number로 이름이 바뀌었을 가능성을 표시한다.
$ tiltmeter check
✗ billing_customers 200 · 13 ms BREAKING · 3 changes
breaking type_changed $.data[*].balance integer → string
breaking field_removed $.data[*].phone string → (absent) possibly renamed to $.data[*].phone_number
info field_added $.data[*].phone_number (absent) → string possibly replaces $.data[*].phone
1 endpoint checked · 1 breaking
$ echo $?
2
예시에서 Claude는 공급업체가 phone을 phone_number로 바꿨을 가능성이 높다고 설명한다. balance가 문자열이 된 상태에서 이 값을 이용해 계산하는 코드는 깨질 수 있으므로 phone_number를 읽고 balance를 숫자로 파싱하라고 제안한다.
타입이 지정된 코드는 API 변경을 만나면 오류를 낸다. 반면 에이전트는 새 응답을 보고 빈틈을 추측으로 메우거나 예산이 소진될 때까지 재시도할 수 있다. Tiltmeter는 명세 없이 실제 응답에서 API 형태를 학습한다. 기준선은 최근 성공한 검사 20건을 합쳐 만든다. 선택적 필드가 빠진 것은 문제로 보지 않지만, 항상 있던 필드가 사라지는 등 서로 모순되는 변화는 감지한다.
- 관찰: 엔드포인트를 호출하고 JSON 본문에서 타입, 필드가 나타난 빈도, 범주형으로 보이는 필드의 값을 파악한다. 예를 들어
balance integer 20/20,phone string 20/20,status active | past_due처럼 기록한다. - 비교:
balance integer → string,phone 20/20 → 0/1처럼 기준선과 달라진 점을 찾는다. - 한 번 알림: CI를 실패시키거나 Slack·웹훅으로 알리고, Claude로 변경 내용을 설명하거나 MCP를 통해 에이전트에 전달한다. 새로운 형태는 기준선에 반영되므로 같은 변경을 한 번 알린다. 예시에서는 종료 코드가 2이고, Slack 채널은
#api-alerts, MCP 결과는has_drifted → true다. - 수정: 에이전트가 API를 읽는 코드를 찾아 고친 뒤 풀 리퀘스트를 연다. 사용자는 차이를 검토한다.
이미 웹 앱에서 API를 호출한다면 브라우저에서 HAR 파일을 내보내 설정을 만들 수 있다. 토큰과 쿠키는 ${VAR} 자리표시자로 바뀐다.
tiltmeter init --from-har session.har --host api.example.com
어떤 변화를 감지하는가
Tiltmeter는 변경을 분류하며, 삭제된 필드와 이름이 비슷한 새 필드가 있으면 이름 변경 가능성을 표시한다. 심각도는 전체 설정이나 엔드포인트별로 바꿀 수 있다.
field_removed: 모든 응답에 있던phone이 사라지면 중대 변경이다.field_now_optional: 항상 있던email이 일부 객체에서 빠지기 시작하면 중대 변경이다.type_changed:balance가 정수에서 문자열로 바뀌면 중대 변경이다.nullable_introduced:phone에null이 들어갈 수 있게 되면 중대 변경이다.content_type_changed: JSON 본문이 HTML 오류 페이지로 바뀌면 중대 변경이다.status_changed: 200에서 503으로 바뀌면 중대 변경, 404에서 200으로 바뀌면 정보, 200에서 202로 바뀌면 경고다. 심각도는 상황에 따라 달라진다.enum_value_added:status에active,past_due외에suspended가 추가되면 경고다.latency_regression: 중앙값 지연 시간이 기준선의 3배를 넘고 250ms 이상 느려지면 경고다.field_added:phone_number같은 필드가 추가되면 정보로 분류한다.
DTO는 유지해도 된다. DTO는 모델로 정의한 필드를 코드가 읽는 시점에 검사한다. Tiltmeter는 코드가 응답을 사용하기 전에 전체 응답을 검사하고 DTO를 바꿔야 할 때 알린다는 것이 제품의 설명이다.
예시에서 공급업체가 phone 이름을 바꾸고 balance를 문자열로 보낸다.
class Customer(BaseModel):
name: str
phone: str
balance: int
Customer.model_validate(response)
ValidationError: 1 validation error for Customer
phone
Field required [type=missing]
balance가 "1200"으로 돌아오면 Pydantic은 이를 1200으로 변환하면서도 알리지 않을 수 있다. 이 값이 센트인지 달러인지는 알 수 없다.
DTO는 문제가 생긴 요청에서 운영 환경 오류를 낸다. Tiltmeter는 일정에 따라 또는 CI에서 검사해 사용자보다 먼저 변경을 발견한다. DTO는 모델에 정의한 필드만 알지만, Tiltmeter는 새 phone_number와 사라진 phone을 함께 보고 이름이 바뀌었을 가능성을 찾는다. 타입 변환이 타입 변경을 감출 수 있지만 Tiltmeter는 정수에서 문자열로의 변화를 중대 변경으로 알린다. 형식 자체가 바뀌었을 수 있기 때문이다. 에이전트는 DTO 없이 원시 JSON을 읽을 수 있으므로 has_drifted를 통해 타입 지정 코드가 받는 검사와 같은 정보를 확인할 수 있다.
Tiltmeter는 변경 기록을 믿기 어려운 소규모 업체와 파트너 API, 다른 팀이 관리하는 내부 API, HAR 파일로 시작하는 웹 앱 뒤의 문서화되지 않은 엔드포인트, 명세가 없는 에이전트 호출 API를 위한 도구라고 소개한다. 반면 Stripe처럼 모든 변경에 버전을 지정하고 특정 버전을 고정할 수 있으며 변경 기록도 공개하는 API에서는 버전을 고정하고 변경 기록을 읽으면 되므로 Tiltmeter의 추가 효과가 크지 않다고 설명한다.
에이전트가 API를 사용하기 전에 확인한다
MCP 서버를 사용하면 Claude Code, Cursor, LangChain 또는 다른 MCP 클라이언트가 API를 신뢰하기 전에 has_drifted를 호출하고, 예상 필드를 확인하려고 get_schema를 사용할 수 있다. 에이전트가 확인할 수 있는 엔드포인트는 설정에 등록된 것뿐이다. 서드파티 API를 사용하기 전에 has_drifted를 호출하고, 변경이 감지되면 요약을 읽고 응답을 신뢰하기 전에 코드와 사용 방식을 조정하라는 안내다.
예시에서 고객 42에게 연체된 청구서를 문자로 알리려는 에이전트는 has_drifted("billing_customers")를 호출한다. 결과는 drifted true, max_severity breaking, phone → phone_number이며 마지막 검사는 2분 전이다. 에이전트는 전화번호 필드가 바뀐 것을 확인하고 빈 번호로 문자를 보내지 않도록 새 필드를 읽는다.
has_drifted: 최근 경고 수준 이상으로 응답이 바뀌었는지 확인한다.get_schema: 예상 필드, 타입, 열거형 값을 JSON Schema로 확인한다.get_changes: 최신순 변경 기록을 확인한다.list_endpoints: 감시 중인 API와 마지막 검사 결과를 확인한다.check_api: API 하나를 지금 호출해 결과를 기록한다.check_all: 등록된 모든 API를 지금 호출한다.
Claude Code 설정 명령은 다음과 같다.
claude mcp add tiltmeter -- uvx tiltmeter serve --config tiltmeter.yaml
프로젝트 폴더에서 실행한다. Cursor는 .cursor/mcp.json에 다음 설정을 넣을 수 있다.
{
"mcpServers": {
"tiltmeter": {
"command": "uvx",
"args": ["tiltmeter", "serve", "--config", "tiltmeter.yaml"]
}
}
}
Codex에서는 다음 명령을 실행하거나 ~/.codex/config.toml에 [mcp_servers.tiltmeter]를 추가한다.
codex mcp add tiltmeter -- uvx tiltmeter serve --config tiltmeter.yaml
OpenCode 설정은 프로젝트의 opencode.json에 넣는다.
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"tiltmeter": {
"type": "local",
"command": ["uvx", "tiltmeter", "serve", "--config", "tiltmeter.yaml"],
"enabled": true
}
}
}
코딩 에이전트에 붙여 넣을 설정 요청은 다음과 같다.
Set up Tiltmeter (https://github.com/tiltmeter-dev/tiltmeter) in this project so you can check whether the third-party APIs we use have changed before relying on them.
1. Find the external HTTP APIs this codebase calls that return JSON.
2. Create tiltmeter.yaml in the project root with one endpoint per API. Use ${ENV_VAR} placeholders for keys, never literal secrets. Docs: https://github.com/tiltmeter-dev/tiltmeter/blob/main/docs/configuration.md
3. Add .tiltmeter/ to .gitignore and run `uvx tiltmeter check` once to record the baselines.
4. Register the MCP server for yourself, using the command: uvx tiltmeter serve --config tiltmeter.yaml
5. Add to CLAUDE.md or AGENTS.md: "Before relying on a third-party API, call the tiltmeter has_drifted tool for it."
Show me the endpoints you chose before writing the file.
이 요청을 코딩 에이전트에 붙여 넣으면 에이전트가 API를 찾고 설정을 작성해 서버를 설치한다는 설명이다.
감지한 변경에서 풀 리퀘스트까지
tiltmeter fix는 변경 내용을 에이전트에 전달한다. 에이전트는 해당 API를 읽는 코드를 찾고 차이를 보여 준 뒤, 사용자가 동의하면 풀 리퀘스트를 연다. 내장 LangChain 에이전트를 실행하거나 API 키 없이 사용자의 Claude Code 또는 Codex 로그인을 이용할 수 있다.
수정 절차는 변경 감지, 작업 트리가 깨끗한지 확인, 에이전트의 코드 수정, 사용자 승인, 풀 리퀘스트 순으로 진행된다. 예시 명령은 다음과 같다.
$ tiltmeter fix 26 --repo ~/code/billing-service
✗ billing_customers #26 · 200 · 13 ms BREAKING · 3 changes
Working on a new branch, tiltmeter/fix-billing-customers-26, from main at 162dadd.
agent is editing the worktree
3 files changed +5 -5
diff --git a/billing/client.py b/billing/client.py
- return f"{customer['name']} <{customer['phone']}>"
+ return f"{customer['name']} <{customer['phone_number']}>"
...
╭─ agent ─────────────────────────────────╮
Billing customer code now reads phone_number instead of phone, in the client, the Customer TypedDict and the test fixture.
Left for a human:
- The format of the string balance is unknown ("1200" or "12.00"). Confirm it with the billing provider.
confidence medium
╰─────────────────────────────────────────╯
Commit, push and open a pull request? [y/N]: y
✓ opened https://github.com/acme/billing-service/pull/41
에이전트는 클라이언트 코드, Customer TypedDict, 테스트 픽스처에서 phone을 phone_number로 바꾼다. 문자열로 바뀐 balance의 형식이 "1200"인지 "12.00"인지는 알 수 없으므로 병합 전에 결제 API 제공업체에 확인해야 한다. Tiltmeter는 타입은 볼 수 있지만 값 자체는 알지 못한다고 설명한다.
코드 변경은 $.data[*].phone이 삭제되고 phone_number로 이름이 바뀌었을 가능성, $.data[*].balance가 정수에서 문자열로 바뀐 점을 따른다. 새 필드, 상태, 지연 시간 변경은 수정 대상에서 제외한다. 작업은 tiltmeter/fix-billing-customers-26 브랜치의 임시 Git worktree에서 진행되며, 원래 체크아웃은 건드리지 않는다. 예시에는 billing/client.py, billing/models.py, tests/conftest.py가 표시되고 .env와 .git은 차단된다. 네트워크도 사용하지 않는다. 사용자가 n을 선택하면 변경을 모두 버린다.
예시 풀 리퀘스트는 billing/client.py와 billing/models.py에서 phone을 phone_number로 바꾼다. balance 형식이 "1200"인지 "12.00"인지는 사람이 제공업체에 확인한 뒤 병합해야 한다.
CI에서 검사하기
GitHub Action은 기준선을 Actions 캐시에 저장하고 변경 내용을 작업 요약에 기록하며, 드리프트가 발견되면 작업을 실패 처리한다. GitLab CI와 cron도 사용할 수 있다. 종료 코드는 다음과 같다.
0: 변경 없음1: 경고2: 중대 변경3: 검사 실행 실패4: 설정 오류
원문에 제시된 GitHub Actions 및 Tiltmeter 설정 예시는 다음과 같다.
# .github/workflows/api-drift.yml
- uses: tiltmeter-dev/tiltmeter-action@v1
env:
PARTNER_API_KEY: ${{ secrets.PARTNER_API_KEY }}
# tiltmeter.yaml
notify:
- type: slack
webhook_url: ${SLACK_WEBHOOK_URL}
API 제공업체가 변경을 함께 알리는 방식
API 제공업체는 자체 도메인에 서명된 공지로 변경을 한 번 설명할 수 있다. 이를 구독한 고객은 기존 응답이 중단되기 전에 코드를 조정하는 풀 리퀘스트를 받는다. 공지가 아직 없다면 고객이 OpenAPI 명세를 직접 구독할 수도 있다. 제공업체 모드 안내
2026년 10월 보고서에서 Tiltmeter는 Stripe와 Spotify가 삭제한 필드를 공개 코드에서 검색했다. Stripe의 API 버전 2025-03-31부터 사라진 subscription.current_period_end를 여전히 읽는 저장소가 78개였고, 2026년 2월 신규 앱에서 바뀐 Spotify 필드와 엔드포인트를 사용하는 저장소가 228개였다. 그중 Stripe 공식 구독 예제는 Stripe 자체 SDK의 타입 검사에 더는 통과하지 않았다. Tiltmeter는 이 예제와 직접 확인한 다른 저장소 14개의 문제를 수정했으며, 풀 리퀘스트는 열려 있다. Stripe 예제 수정
이후 Tiltmeter는 Stripe, Jira, Spotify, OpenAI, Anthropic, Groq, Slack, OpenWeatherMap의 변경을 대상으로 풀 리퀘스트 64개를 열었다. 그중 1개는 닫혔고 5개는 병합됐다. 병합된 변경은 모두 Tiltmeter가 작성했다. Serenity BDD는 Jira Cloud가 제거한 /rest/api/3/search에서 Jira 플러그인을 옮겼다. ruflo, radare2의 r2ai, mcp-chat는 Anthropic이 종료한 Claude 모델에서 기본값을 바꿨다. KindleEar는 Groq가 종료한 모델에서 기본값을 바꿨다. 제공업체별 풀 리퀘스트와 상태
명세 비교 도구와의 차이 및 데이터 처리
OpenAPI 차이 비교 도구는 제공업체가 명세를 관리하는 경우 두 버전을 비교하지만, 문서에 기록되지 않은 변경은 찾지 못한다. 계약 테스트는 제공업체가 테스트를 실행해야 하며, 서드파티 업체는 보통 그렇게 하지 않는다. 가동 상태 감시 도구는 API가 작동하는지 알려 주지만 응답 검증문은 사용자가 작성하고 관리해야 한다. Tiltmeter는 실제 응답에서 계약을 학습해 문서화되지 않은 변경을 감지하고, 학습한 정보를 에이전트에 제공한다고 설명한다.
데이터는 로컬에 저장된다는 것이 제품 설명이다. 계정 없이 SQLite 파일 하나를 사용하며, 저장하는 항목은 응답 형태, 상태 코드, 지연 시간, 변경 사항이다. 응답 본문은 샘플 저장을 켠 경우에만 보관한다. 비밀 값은 환경 변수에 남는다. ${VAR} 값은 요청 시 확장되며 디스크에 기록되거나 LLM에 전송되지 않는다. 모델에는 사용자가 허용한 정보만 전달한다. 변경 설명과 수정 작업에는 변경 목록과 에이전트가 여는 파일만 제공하며 응답 값은 전달하지 않는다.
Tiltmeter는 오픈소스 MIT 라이선스 제품이며 Python 3.12 이상에서 사용할 수 있다고 안내한다.
pip install tiltmeter
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요