Communitygithub.com

vellum-ai/vellum-assistant

透過 OAuth2 連接 Oura Ring — 應用程式註冊、Token 交換及憑證儲存

vellum-assistant 是什麼?

此技能提供完整的 Oura Ring 整合流程,讓 AI 助手能夠安全地連接使用者的 Oura Ring,並透過 Oura Cloud API V2 取得睡眠、心率、準備度、活動等健康資料。它涵蓋了從開發者應用程式註冊、OAuth2 授權流程(包含自動捕捉授權碼並交換 Token 的 Python 輔助腳本),到憑證安全儲存與 Token 自動重新整理的完整步驟。支援 Cursor 等具備 `host_bash` 權限的平台,讓使用者無需手動複製貼上授權碼,即可在瀏覽器中完成授權。此整合對於需要即時存取穿戴裝置健康數據的個人化健康助理、日報生成或數據分析應用非常實用。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/vellum-ai/vellum-assistant/tree/HEAD/skills/oura-setup

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

Oura Ring 整合

連接使用者的 Oura Ring,透過 Oura Cloud API V2 提取睡眠、心率、準備度、活動及其他健康資料。

先決條件

  • Oura Ring(Gen 3 或 Ring 4)且擁有有效的 Oura 會員資格(API 存取需每月 $6 美元)
  • 已安裝 Oura 應用程式並與戒指配對
  • 在 https://cloud.ouraring.com 擁有 Oura Cloud 帳戶

設定

1. 註冊開發者應用程式

請使用者前往 https://developer.ouraring.com/applications 並建立一個新的應用程式:

  • 顯示名稱: 使用者偏好的整合名稱
  • 描述: 整合的簡短描述
  • 聯絡 Email: 使用者的電子郵件
  • 網站: 任何有效的 URL(例如個人網站)
  • 隱私權政策 / 服務條款: 任何有效的 URL(個人應用為必填欄位,但不強制審查)
  • 重新導向 URI: http://localhost:3000/callback
  • 範圍: 啟用所有需要的範圍。建議啟用:personal、daily、heartrate、sleep、workout、spo2、stress、heart_health、session、ring_configuration

儲存用戶端 ID 和用戶端密鑰。

2. 執行 OAuth 流程

使用 assistant credentials prompt 安全地儲存用戶端密鑰,然後在使用者的機器上編寫並執行 OAuth 輔助腳本:

#!/usr/bin/env python3
"""Oura Ring OAuth2 輔助工具 — 立即捕捉授權碼並交換 Token。"""
from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import urlparse, parse_qs, urlencode
import urllib.request, json, webbrowser, ssl

CLIENT_ID = 'YOUR_CLIENT_ID'
CLIENT_SECRET = 'YOUR_CLIENT_SECRET'
REDIRECT_URI = 'http://localhost:3000/callback'
SCOPES = 'email personal daily heartrate workout tag session spo2 ring_configuration stress heart_health'

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        parsed = urlparse(self.path)
        if parsed.path == '/':
            params = urlencode({
                'response_type': 'code', 'client_id': CLIENT_ID,
                'redirect_uri': REDIRECT_URI, 'scope': SCOPES, 'state': 'assistant'
            })
            self.send_response(302)
            self.send_header('Location', f'https://cloud.ouraring.com/oauth/authorize?{params}')
            self.end_headers()
        elif parsed.path == '/callback':
            code = parse_qs(parsed.query).get('code', [''])[0]
            if code:
                token_data = urlencode({
                    'grant_type': 'authorization_code', 'code': code,
                    'redirect_uri': REDIRECT_URI, 'client_id': CLIENT_ID,
                    'client_secret': CLIENT_SECRET,
                }).encode()
                try:
                    req = urllib.request.Request('https://api.ouraring.com/oauth/token',
                        data=token_data,
                        headers={'Content-Type': 'application/x-www-form-urlencoded'},
                        method='POST')
                    resp = urllib.request.urlopen(req, context=ssl.create_default_context())
                    result = json.loads(resp.read())
                    with open('/tmp/oura_tokens.json', 'w') as f:
                        json.dump(result, f, indent=2)
                    self.send_response(200)
                    self.send_header('Content-Type', 'text/html')
                    self.end_headers()
                    self.wfile.write(b'<html><body><h1>已連線!您可以關閉此分頁。</h1></body></html>')
                    print(f'\nToken 已儲存至 /tmp/oura_tokens.json')
                except Exception as e:
                    self.send_response(500)
                    self.end_headers()
                    self.wfile.write(f'Token 交換失敗:{e}'.encode())
    def log_message(self, *a): pass

print('正在開啟瀏覽器進行 Oura 授權...')
webbrowser.open('http://localhost:3000')
HTTPServer(('localhost', 3000), Handler).serve_forever()

在使用者的機器上執行 python3 /path/to/script.py(host_bash)。使用者在瀏覽器中授權後,腳本會立即捕捉授權碼並交換成 Token,過程不到一秒。

重要: 授權碼約在 30 秒內過期。請勿讓使用者手動貼上授權碼 — 請使用此腳本自動捕捉並交換。

3. 儲存 Token

OAuth 流程完成後,從 /tmp/oura_tokens.json 讀取 Token 並儲存:

  • access_token — 儲存至憑證庫,使用注入模板為 api.ouraring.com 的 Authorization 標頭(Bearer 前綴)以及 allowed_tools: ["bash"]
  • refresh_token — 儲存至憑證庫,用於 Token 重新整理
  • Token 約在 30 天後過期。請在過期前設定提醒進行重新整理。

4. 驗證連線

使用個人資訊端點進行測試:

curl -s -H "Authorization: Bearer $TOKEN" "https://api.ouraring.com/v2/usercollection/personal_info"

可用端點

所有端點皆使用 GET https://api.ouraring.com/v2/usercollection/{type},並搭配查詢參數 start_date 和 end_date(YYYY-MM-DD 格式)。

端點資料備註
/v2/usercollection/daily_sleep睡眠分數、持續時間、效率、睡眠階段建議在使用者通常起床時間後查詢
/v2/usercollection/sleep詳細睡眠週期,包含心率、HRV、動作原始睡眠週期資料
/v2/usercollection/daily_readiness準備度分數、HRV 平衡、恢復狀態早晨健康指標
/v2/usercollection/daily_activity步數、卡路里、活動量、不活動時間活動摘要
/v2/usercollection/heartrate連續心率(使用 start_datetime/end_datetime,ISO 格式)資料量可能很大 — 請限制日期範圍
/v2/usercollection/daily_spo2血氧濃度夜間平均值
/v2/usercollection/daily_stress壓力分數與恢復日間壓力追蹤
/v2/usercollection/workout偵測到的運動,包含心率、卡路里自動偵測或手動輸入
/v2/usercollection/personal_info年齡、體重、身高、電子郵件良好的連線測試端點

Token 重新整理

Token 會在 30 天後過期。使用以下方式重新整理:

curl -s -X POST "https://api.ouraring.com/oauth/token" \
  -d "grant_type=refresh_token&refresh_token=$REFRESH_TOKEN&client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET"

從回應中儲存新的 access_token 和 refresh_token。

技巧

  • 新戒指需要 1-2 晚進行校準,資料才會有意義
  • 睡眠資料通常在使用者起床後數小時才會出現
  • 運動期間的心率資料會在運動透過 Oura 應用程式同步後出現
  • 速率限制:每 5 分鐘 5000 次請求
  • Ring 4 和 Gen 3 使用者必須擁有有效的 Oura 會員資格才能使用 API

相關技能