מדריך קלוד קוד בעברית

תיעוד 111

תצורת שער יישומי Claude

מדריך לכל אפשרות ב-gateway.yaml: מאזין ו-TLS, OIDC, סשן, מאגר Postgres, upstreams של Amazon Bedrock, Claude Platform on AWS, Agent Platform של Google Cloud ו-Microsoft Foundry, ניתוב מודלים, מדיניות מנוהלת וטלמטריה.

פריסת שער יישומי Claude מוגדרת בקובץ YAML אחד, בדרך כלל gateway.yaml. הקובץ מגדיר את כל מה שהשער עושה: איפה הוא מאזין, איך מפתחים נכנסים, לאן הולכת ההסקה, ואילו מדיניות וטלמטריה חלות. הדף הזה הוא המדריך לכל אפשרות בקובץ.

כדי לכתוב את הראשון, התחילו מההתחלה המהירה, שבונה תצורה מינימלית עובדת ומריצה אותה. אחרי שיש תצורה שאתם מרוצים ממנה, מדריך הפריסה מכסה אריזה בקונטיינר ואירוח ב-Kubernetes, ב-Cloud Run, או בפלטפורמה שלכם.

השער קורא את הקובץ פעם אחת, בעת ההפעלה, באמצעות claude gateway --config /path/to/gateway.yaml. כל אפשרות מאומתת מול סכמה בזמן האתחול, ולכן תצורה לא תקינה נכשלת בהפעלה עם שגיאה ברמת השדה, ולא בשימוש הראשון.

הדוגמה המלאה בסוף הדף הזה מפעילה כל מקטע.

#מבנה הקובץ

חמישה מקטעים הם חובה. כל מקטע אחר הוא אופציונלי, ומקטע שהושמט מקבל את ברירות המחדל שלו. מפתחות לא מוכרים נכשלים באתחול, ולכן שגיאת הקלדה מופיעה כשגיאה עם שם, ולא כהגדרה שמתעלמים ממנה בשקט.

מקטעי חובה:

  • listen: כתובת bind, כתובת URL ציבורית, סיום TLS
  • oidc: ספק הזהות (IdP), כולל issuer, client, מיפוי claim, ומי רשאי להיכנס
  • session: אסימוני bearer שהשער מנפיק, עם סוד ומשך חיים
  • store: PostgreSQL, עבור device grants ומוני הגבלת קצב
  • upstreams: לאן הולכת ההסקה, בין אם Anthropic, Amazon Bedrock, Claude Platform on AWS, Agent Platform של Google Cloud, או Microsoft Foundry

מקטעים אופציונליים:

  • admin: אימות Admin API ושמירה עבור מגבלות הוצאה
  • enforcement: התנהגות fail-open או fail-closed של מגבלת הוצאה
  • pricing: תעריפים חוזיים ומכפיל עבור מד ההוצאה ועבור נתוני העלות שהמפתחים רואים
  • models ו-auto_include_builtin_models: רשימת מודלים שנבחרה על ידי מנהל ומזהים לפי upstream
  • managed: מדיניות הגדרות מנוהלות לפי קבוצת IdP
  • telemetry: העברת OTLP אל מחסנית התצפית שלכם
  • access_control, limits, timeouts, rate_limits: הרשאה או חסימה של IP, תקרות גודל בקשה, זמן עד הבייט הראשון מה-upstream, ומגבלות כניסה לפי IP
  • load_test_mode: בדיקת עומס של השער בלי קריאה לספק מודל

#הרחבת סודות

אל תכתבו סודות כמו client_secret, jwt_secret, או postgres_url ישירות ב-gateway.yaml. הפנו אליהם באחת מהצורות למטה, והשער פותר את הערך בזמן האתחול ממשתנה סביבה או מקובץ:

צורהנפתר אלשימוש עבור
${VAR}משתנה הסביבה VAR. האתחול נכשל אם הוא לא מוגדר.משתני סביבה של קונטיינר, AWS Secrets Manager באמצעות הזרקת env
${file:/path}תוכן הקובץ בנתיב המוחלט הזה, אחרי הסרת רווחים בקצוות. ההפניה חייבת להיות כל ערך השדה: בניגוד ל-${VAR}, היא לא מורחבת בתוך מחרוזת ארוכה יותר, ולכן עבור סיסמת מסד נתונים הגדירו store.password במקום להטמיע אותה ב-postgres_url.עגינות volume של Kubernetes Secret, Vault Agent, SOPS

#מקטעי חובה

#listen

בלוק listen שולט איפה השער משרת: כתובת ה-bind והפורט, ה-origin הנראה כלפי חוץ, וסיום TLS אופציונלי.

שדהחובהתיאור
hostלאכתובת bind. ברירת מחדל 0.0.0.0.
portלאפורט bind. ברירת מחדל 8080.
public_urlאלא אם host הוא loopbackה-origin הנראה כלפי חוץ בצורת https://, שמשמש לבניית redirect_uri של ה-IdP ולמטא-נתוני discovery. נדרש בכל פעם ש-host אינו כתובת loopback, בין אם TLS מסתיים בפרוקסי כגון ALB, Ingress, או Cloud Run ובין אם בשער עצמו דרך tls, מפני שהשער אף פעם לא גוזר את ה-origin שלו מכותרות X-Forwarded-*: אפשר לזייף אותן מצד הלקוח. האתחול נכשל בלעדיו. trusted_proxies למטה חל רק על זיהוי כתובת ה-IP של הלקוח. נדרש גם כדי להפעיל טלמטריה, מפני שהשער בונה מכתובת ה-URL הזו את נקודת הקצה של OTLP שהוא דוחף ללקוחות.
tls.cert / tls.keyלאנתיבי PEM אם השער עצמו מסיים TLS
trusted_proxiesלאכתובות CIDR או IP של מאזני עומסים לפני השער. כשהשדה מוגדר, השער סומך על X-Forwarded-For רק מהעמיתים האלה ורושם את כתובת ה-IP האמיתית של הלקוח עבור הגבלת קצב לפי IP ועבור ביקורת. שקול ל-set_real_ip_from של nginx. רשומות X-Forwarded-For שנכתבות כ-ipv4:port או [ipv6]:port, כמו שחלק ממאזני העומסים עושים, נקראות כשהפורט מוסר. כתובת IPv6 עם פורט שנוסף ובלי סוגריים עלולה להיקרא ככתובת אחרת או לא להיקרא בכלל, ולכן כבו את אפשרות הפורט בכל פרוקסי שכותב את הצורה הזו.

#oidc

בלוק oidc מחבר את ה-gateway לספק הזהות ומחליט מי יכול להתחבר. הוא מציין את ה-issuer ואת לקוח ה-OAuth, ממפה את ה-claims שנושאים אימייל וקבוצות, ומגביל התחברות לפי דומיין אימייל או קבוצה.

OpenID Connect (OIDC) הוא פרוטוקול ה-SSO שה-gateway משתמש בו עם ספק הזהות. ראו הגדרת ספק זהות לגבי מה לרשום בצד ה-IdP.

שדהחובהתיאור
issuerכןבסיס גילוי OIDC. חייב להגיש גילוי ב-/.well-known/openid-configuration. השתמשו ב-HTTPS בסביבת ייצור. ה-gateway מקבל issuer ב-http://. issuer מסוג loopback כגון http://localhost:8081 נדחה על ידי מגן ה-SSRF אלא אם CLAUDE_GATEWAY_ALLOW_LOOPBACK=1 מוגדר בסביבת ה-gateway.
client_idכןמרישום לקוח ה-OAuth שלכם
client_secretאלא אם token_endpoint_auth_method הוא private_key_jwtמרישום לקוח ה-OAuth שלכם. השמיטו אותו כשמשתמשים באימות לקוח בתעודה.
allowed_email_domainsלאדחיית id_tokens שה-claim email שלהם אינו באחד מהדומיינים האלה, בלי תלות ברישיות. הגנה לעומק מפני תצורה שגויה של IdP מרובה דיירים. בנפרד מההגדרה הזו, id_token שה-claim email_verified שלו הוא במפורש false נדחה תמיד.
allowed_groupsלאהגבלת התחברות לחברים בקבוצות IdP אלה, בהתאמה ל-groups_claim. משתמש בדומיין אימייל מותר שאינו באף אחת מהקבוצות האלה נדחה. נדרש שה-IdP יפיק את claim הקבוצות. ההתאמה היא השוואת מחרוזת מדויקת ותלוית רישיות מול הערכים ב-claim הזה, וה-gateway אינו מרחיב קבוצות מקוננות: כדי לאשר חברים בתת-קבוצה, ציינו כאן את תת-הקבוצה או הגדירו את ה-IdP כך שיפיק חברות שטוחה.
groups_claimלאאיזה claim ב-id_token נושא חברות בקבוצות. ברירת המחדל היא groups. Microsoft Entra מפיק תפקידי אפליקציה תחת roles. מקבל מפתח שטוח או JSON Pointer לפי RFC 6901 כגון /resource_access/gateway/roles ל-claims מקוננים.
google_groupsלאאיתור קבוצות המשתמש שהתחבר דרך Google Workspace Admin SDK Directory API, כי ה-id_token של Google אינו נושא claim קבוצות. הגדירו את service_account_json_path לקובץ מפתח של חשבון שירות עם האצלה ברמת הדומיין על ה-scope https://www.googleapis.com/auth/admin.directory.group.readonly, ואת admin_email למנהל Workspace שחשבון השירות מתחזה אליו. ה-Directory API דורש subject של מנהל אמיתי. כתובות האימייל של הקבוצות של כל משתמש הופכות ל-claim הקבוצות שלו, ולכן allowed_groups ו-managed.policies.match.groups מתאימים לפי אימייל של קבוצה.
email_claimלאאיזה claim ב-id_token נושא את האימייל של המשתמש. ברירת המחדל היא email. חלק מספקי ה-IdP, כגון ADFS ו-Entra B2C, מפיקים upn או preferred_username במקום זאת. מקבל מפתח שטוח, JSON Pointer, או רשימת מפתחות גיבוי שבה נעשה שימוש במפתח הראשון שקיים.
scopesלאדריסה מלאה של ה-scopes של OIDC שה-gateway מבקש. ברירת המחדל היא [openid, profile, email, offline_access]. הגדירו כשה-IdP דוחה scopes שהוא אינו מזהה, או כשנדרש scope מותאם אישית כדי להפיק קבוצות או אימייל. חייב לכלול את openid. השמטת offline_access משביתה refresh tokens, ולכן מפתחים מריצים מחדש את התחברות הדפדפן בכל session.ttl_hours. ראו הגדרת ספק זהות למתכוני scope לפי IdP, כגון זרימת ה-refresh token של Google.
scope_on_refreshלאשליחה גם של scope, עם אותה רשימה כמו בבקשת ההתחברות, כשה-gateway מחליף refresh token. ברירת המחדל היא false: בקשת ה-refresh משמיטה את scope. רוב ספקי ה-IdP מחזירים id_token בכל refresh ואינם זקוקים לכך. הגדירו true כשה-IdP מחזיר id_token ב-refresh רק אם מבקשים שוב את openid, מה ש-Okta מתעד עבור ה-refresh grant שלו. בלי id_token, כל refresh תלוי בכך שנקודת הקצה userinfo של ה-IdP תקבל את ה-access token המרוענן. אם אתם מגבילים התחברות או מתאימים מדיניות לפי קבוצות, וה-id_token בזמן refresh של ה-IdP משמיט אותן, הגדירו גם userinfo_fallback: true כדי שה-gateway ישלים אותן מנקודת הקצה userinfo. IdP שהעניק פחות scopes ממה שהתבקש יכול לדחות את ה-refresh עם invalid_scope, כולל עבור סשנים קיימים אם מוסיפים רשומות ל-scopes בזמן שההגדרה הזו פעילה. בטלו את המפתח אם רענונים מתחילים להיכשל ב-token_endpoint אחרי שהגדרתם אותו. נדרש Claude Code v2.1.260 או חדש יותר בשרת ה-gateway.
extra_auth_paramsלאפרמטרי שאילתה נוספים שמצורפים לבקשת ההרשאה של ה-IdP, כלשונם. זה מנגנון הדריסה להתנהגות ייחודית ל-IdP, כגון access_type: offline עבור refresh tokens של Google, domain_hint עבור חלק מדיירי Entra, או acr_values עבור זרימות step-up. אי אפשר לדרוס את פרמטרי הפרוטוקול שה-gateway מנהל: state, nonce, redirect_uri, PKCE, scope, response_type, response_mode ו-client_id.
userinfo_fallbackלאכשה-id_token משמיט אימייל או קבוצות, שלוף אותם מ-/userinfo. נדרש עבור lightweight access tokens של Keycloak, שרת הארגון של Okta, וטוקנים מינימליים של ADFS. ה-id_token נשאר הסמכותי. userinfo רק ממלא פערים. ברירת המחדל היא false.
use_pkceלאשליחת אתגר PKCE ‏(S256) בבקשת ההרשאה. ברירת המחדל היא true. הגדירו false רק אם ה-IdP דוחה PKCE עבור הלקוח הסודי הזה.
clock_skew_secondsלאסובלנות לסטיית שעון בעת אימות claims של זמן ב-id_token. ברירת המחדל היא 0, וזו בדיקה מחמירה. העלו אם אתם רואים שגיאות "token expired / not yet valid" מיד אחרי התחברות בגלל סטיית שעון בין המארח ל-IdP.
token_endpoint_auth_methodלאאיך ה-gateway מאמת את עצמו מול נקודת הקצה token של ה-IdP: client_secret_basic, client_secret_post, או private_key_jwt עבור אימות לקוח בתעודה. כברירת מחדל ה-gateway בוחר אחת משתי שיטות ה-client_secret לפי מה שה-IdP מפרסם.
client_assertionעם private_key_jwtבלוק עם private_key_pem ו-certificate_pem: המפתח הפרטי והתעודה עבור אימות לקוח בתעודה. נדרש v2.1.284 או חדש יותר.
id_token_signed_response_algלאאלגוריתם החתימה הצפוי של id_token. ברירת המחדל היא RS256. הגדירו עבור IdP שחותם ב-ES256, ב-PS256 או ב-EdDSA.
additional_authorized_partiesלאערכי azp נוספים לקבלה מעבר ל-client_id, עבור זרימות broker ו-token-exchange של Keycloak
discovery_urlלאשליפת מסמך הגילוי מכתובת ה-URL הזו במקום לגזור אותו מ-issuer, עבור IdP מאחורי פרוקסי שמשכתב את מארח ה-issuer. הנתיב חייב להכיל /.well-known/.
use_proxyלאשליחת בקשות ה-IdP של ה-gateway עצמו דרך ה-forward proxy ב-HTTPS_PROXY או ב-HTTP_PROXY, תוך כיבוד NO_PROXY. false משאיר את הבקשות האלה ישירות. נדרש v2.1.227 או חדש יותר. ראו בקשות IdP דרך forward proxy בהמשך.
form_action_originsלאמקורות נוספים עבור ההנחיה Content-Security-Policy: form-action של דף /device. ה-gateway כבר מתיר את 'self' ואת מקור ה-authorization_endpoint שהתגלה, אבל Chrome אוכף את form-action מול כל שרשרת ההפניות. אם ה-IdP מפנה דרך מארח שני, כגון Azure AD שמאוחד ל-ADFS, Okta במבנה hub-spoke, או מיירט SSO ארגוני, ציינו כל מקור שבקשת ההרשאה עשויה לעבור דרכו בהפניה.
ca_cert_pemלאתעודת ה-CA עצמה בקידוד PEM, ולא נתיב לקובץ. היא מחליפה את מאגר האמון של המערכת עבור בקשות IdP בלבד. כדי לטעון קובץ מורכב, כתבו ${file:/etc/gateway/idp-ca.pem}. השתמשו עבור Keycloak או Dex מאחורי PKI ארגוני.

#אימות לקוח בתעודה

אם ספק הזהות מאמת לקוחות OAuth בתעודה במקום ב-client secret, כפי ש-Microsoft Entra עושה עם אישורי תעודה, הגדירו token_endpoint_auth_method: private_key_jwt. נדרש Claude Code v2.1.284 או חדש יותר בשרת ה-gateway.

בתצורה הזו ה-gateway אינו שולח סוד. הוא מאמת את עצמו מול נקודת הקצה token של ה-IdP באמצעות JWT קצר מועד החתום במפתח הפרטי של התעודה, כשמפתח מתחבר ובכל פעם שה-gateway מרענן את הסשן שלו. ה-JWT חתום ב-RS256 ומזהה את התעודה בכותרות טביעת אצבע x5t ו-x5t#S256, ולא ב-kid. ה-IdP שלכם חייב להיות מסוגל למצוא את התעודה הרשומה לפי טביעת אצבע.

1. יצירת המפתח והתעודה

צרו מפתח פרטי RSA לא מוצפן של לפחות 2048 ביט, בצורת PEM של PKCS#8 או PKCS#1, ותעודה עבורו. ה-gateway מסרב לעלות עם כל מפתח שאינו עומד בתנאים האלה. פקודת openssl הזו יוצרת מפתח כזה עם תעודה בחתימה עצמית שתקפה לשנה אחת:

openssl req -x509 -newkey rsa:2048 -nodes -keyout idp-client.key -out idp-client.crt -days 365 -subj "/CN=claude-gateway"

היא כותבת את idp-client.key ואת idp-client.crt לתיקייה הנוכחית. העתיקו או הרכיבו את שני הקבצים במקום שה-gateway יכול לקרוא אותו. הדוגמה בשלב 3 משתמשת ב-/etc/gateway/.

2. העלאת התעודה ל-IdP

העלו את התעודה, לא את המפתח הפרטי, לרישום האפליקציה של ה-gateway ב-IdP.

3. הוספת המפתח והתעודה ל-gateway.yaml

תנו ל-gateway את המפתח הפרטי ואת התעודה בבלוק client_assertion. השמיטו את client_secret, כי ה-gateway מסרב לעלות כשאחד מהם מוגדר יחד עם private_key_jwt. בלוק oidc הזה מאמת את ה-gateway מול דייר Microsoft Entra בתעודה:

oidc:
  issuer: https://login.microsoftonline.com/<tenant-id>/v2.0
  client_id: <application-id>
  token_endpoint_auth_method: private_key_jwt
  client_assertion:
    private_key_pem: ${file:/etc/gateway/idp-client.key}
    certificate_pem: ${file:/etc/gateway/idp-client.crt}

שני הערכים הם תוכן PEM, לא נתיבי קבצים, ולכן טענו קבצים מורכבים עם ${file:/path} כפי שהדוגמה עושה. ה-gateway מסרב לעלות אלא אם certificate_pem הוא תעודת PEM יחידה, בלי שאר השרשרת שלה, והמפתח הציבורי שלה תואם ל-private_key_pem.

4. הפעלה מחדש של ה-gateway ובדיקת יומן העלייה

הפעילו מחדש את ה-gateway ומצאו את השורה הזו ביומן העלייה:

[gateway] 2026-10-01T23:07:40.512Z info oidc: client authentication private_key_jwt; certificate CN=claude-gateway, SHA-1 thumbprint DE92821854EE8BAA1D98C758FAA04AABE80B9F57, expires Oct  1 23:07:31 2027 GMT

השוו את טביעת האצבע SHA-1 לזו שה-IdP מציג עבור התעודה שהעליתם. אם התעודה פגה או עדיין אינה תקפה, ה-gateway עדיין עולה אבל רושם אזהרה שהתחברויות ורענונים ייכשלו עד שתחליפו אותה. כדי לאשר שה-IdP מקבל את התעודה, בקשו ממפתח אחד להתחבר דרך ה-gateway.

#סיבוב תעודת הלקוח

ה-gateway קורא את המפתח ואת התעודה פעם אחת בעלייה, ולכן קובץ שהשתנה נכנס לתוקף רק אחרי הפעלה מחדש. סובבו בסדר הזה כדי שאף בקשת טוקן לא תציג תעודה שאין ל-IdP:

  1. העלו את התעודה החדשה ל-IdP לצד התעודה הישנה.
  2. החליפו את קובצי המפתח והתעודה ש-gateway.yaml טוען, ואז הפעילו מחדש את ה-gateway. אם אתם מריצים כמה עותקים, הפעלה מחדש מתגלגלת מתאימה, כי ל-IdP יש את שתי התעודות עד שתסירו את הישנה.
  3. אחרי שכל עותק הופעל מחדש, הסירו את התעודה הישנה מה-IdP.

#בקשות IdP דרך forward proxy

ה-upstreams של ההסקה מכבדים את HTTPS_PROXY ואת HTTP_PROXY בכל גרסה. הבקשות של ה-gateway עצמו אל ה-IdP, גילוי, JWKS, token ו-userinfo, הולכות ישירות אלא אם מגדירים oidc.use_proxy: true, מה שדורש v2.1.227 או חדש יותר. כשמשתנה פרוקסי מוגדר, use_proxy אינו מוגדר, וה-issuer אינו מכוסה על ידי NO_PROXY, ה-gateway משאיר את הבקשות האלה ישירות ורושם הודעה בעלייה שמבקשת מכם לבחור. use_proxy: false משאיר אותן ישירות ומשתיק את ההודעה.

עם use_proxy: true, ה-pod פותר בעצמו את שם המארח של כל נקודת קצה של ה-IdP ומבקש מהפרוקסי CONNECT לכתובת ה-IP שנפתרה, ולכן הפרוקסי חייב לקבל CONNECT לכתובת ה-IP של כל מארח שמסמך הגילוי מציין, ולא רק של ה-issuer. השתמשו בכתובת URL של פרוקסי ב-http://. ca_cert_pem ומגן ה-SSRF חלים גם על הנתיב דרך הפרוקסי.

יציאה דרך פרוקסי בלבד משנה את שני אלה: בזמן שהיא פעילה, בקשות IdP עוקבות אחרי הפרוקסי אלא אם מגדירים use_proxy: false, וה-gateway מוסר לפרוקסי כל שם מארח של IdP בלי לפתור אותו קודם.

#יציאה דרך פרוקסי בלבד

הגדירו CLAUDE_GATEWAY_PROXY_IS_EGRESS_BOUNDARY=1 בסביבת ה-gateway, ליד HTTPS_PROXY, כשה-pod מגיע למארחים אחרים רק דרך ה-forward proxy הזה ואינו יכול לפתור בעצמו שמות DNS ציבוריים, או כשהפרוקסי מסרב ל-CONNECT לכתובת IP. נדרש v2.1.277 או חדש יותר. זה משתנה סביבה ולא מפתח ב-gateway.yaml, כדי ששום דבר בקובץ התצורה לא יוכל לרכך את בדיקת הכתובות של ה-gateway.

export HTTPS_PROXY=http://proxy.corp.example.com:3128
export NO_PROXY=
export no_proxy=
export CLAUDE_GATEWAY_PROXY_IS_EGRESS_BOUNDARY=1

ה-gateway רושם שורת network: אחת בעלייה בזמן שיציאה דרך פרוקסי בלבד פעילה.

כל שורה למטה היא מחלקה אחת של בקשה יוצאת ב-gateway שבו HTTPS_PROXY מוגדר, כברירת מחדל ובזמן שיציאה דרך פרוקסי בלבד פעילה.

בקשה יוצאתברירת מחדליציאה דרך פרוקסי בלבד פעילה
upstreams של provider: anthropic, החלפת טוקן של Workload Identity Federation, ייצוא telemetry.forward_toנפתר ונבדק מקומית, ואז CONNECT לכתובת ה-IP שנבדקה דרך הפרוקסי. אספן טלמטריה שרשום ב-NO_PROXY מושג ישירות במקום זאתשם המארח נמסר לפרוקסי
גילוי IdP, JWKS, token ו-userinfoישיר אלא אם oidc.use_proxy: true, ואז CONNECT לכתובת ה-IP שנבדקהשם המארח נמסר לפרוקסי, אלא אם oidc.use_proxy: false משאיר IdP פנימי ישיר
upstreams של Amazon Bedrock, Claude Platform on AWS, Agent Platform של Google Cloud ו-Microsoft Foundry, ואיתור קבוצות Googleשם המארח נמסר לפרוקסיללא שינוי

יציאה דרך פרוקסי בלבד נשארת כבויה אלא אם סביבת ה-gateway עומדת בכל שלושת התנאים האלה:

  • HTTPS_PROXY או HTTP_PROXY מוגדר.
  • NO_PROXY ו-no_proxy ריקים. אם הפלטפורמה מזריקה אחד מהם ל-pods, הגדירו את שניהם לערך ריק במכולת ה-gateway. רישום אספן טלמטריה ב-NO_PROXY משאיר את היציאה דרך פרוקסי בלבד כבויה.
  • CLAUDE_GATEWAY_ALLOW_LOOPBACK אינו מופעל. אספן או IdP על ה-loopback של ה-pod עצמו אינם יכולים להשתלב עם יציאה דרך פרוקסי בלבד, כי כתובת loopback שנמסרת לפרוקסי תהיה של מארח הפרוקסי עצמו, ולכן תנו לשירותים האלה כתובת שהפרוקסי יכול להגיע אליה. מאותה סיבה ה-gateway מסרב לחלוטין לשמות בסגנון localhost בזמן שיציאה דרך פרוקסי בלבד פעילה.

כשאחד מהתנאים האלה אינו מתקיים, ה-gateway רושם אזהרה בעלייה שמציינת את המשתנה שעצר אותו, ושומר על התנהגות ברירת המחדל.

אחרי שיציאה דרך פרוקסי בלבד פעילה, התירו כל יעד בפרוקסי, כולל אספן פנימי וכל מארח שמוגדר לפי כתובת IP. עדיין אפשר להשאיר IdP פנימי ישיר עם oidc.use_proxy: false.

[!WARNING]

הפעילו זאת רק כשרשימת ההיתרים של הפרוקסי מחמירה לפחות כמו הבדיקה של ה-gateway עצמו. הפרוקסי חייב לסרב לנקודות קצה של מטא-דאטה בענן כגון 169.254.169.254 ו-metadata.google.internal, לכתובות link-local, ול-loopback של מארח הפרוקסי עצמו, והוא חייב לסרב להן לפי הכתובת ששם נפתר אליה, ולא רק לפי השם, כי ה-gateway כבר אינו תופס שם מארח שנפתר לאחת מהן. פרוקסי שמתחבר לכל מקום שמבקשים ממנו מסיר את מגן ה-SSRF של ה-gateway עבור הבקשות האלה.

#session

בלוק session מעצב את ה-bearer tokens שה-gateway מנפיק אחרי התחברות: הסוד שחותם אותם ומשך החיים שלהם.

שדהחובהתיאור
jwt_secretכןלפחות 32 בתים של אנטרופיה, לדוגמה מ-openssl rand -base64 32. חותם את ה-bearer tokens של ה-gateway ב-HS256. מקבל מחרוזת יחידה או מערך לסיבוב: אינדקס 0 חותם וכל הרשומות מאמתות. כדי לסובב, הוסיפו סוד חדש בהתחלה, המתינו ttl_hours, ואז הסירו את הישן.
ttl_hoursלאמשך החיים של bearer token של ה-gateway. ברירת המחדל היא 1. ה-CLI מרענן בשקט לפני התפוגה כשה-IdP מנפיק refresh tokens. משך חיים קצר יותר מבטל הקצאה מהר יותר. משך חיים ארוך יותר יוצר פחות הלוך ושוב ל-IdP. אם ה-IdP אינו יכול להנפיק refresh tokens כי offline_access אינו זמין, אין רענון שקט, ולכן העלו זאת ל-8 או ל-12 כדי להימנע משליחת מפתחים חזרה להתחברות בדפדפן בכל שעה.

#store

בלוק store מפנה את ה-gateway אל מסד הנתונים PostgreSQL שלו, שמחזיק הרשאות מכשירים ומונים של הגבלת קצב.

שדהחובהתיאור
postgres_urlכןכתובת postgres:// או postgresql:// עם מארח אחד, לא רשימה מופרדת בפסיקים. ה-gateway מריץ את מיגרציות הסכמה שלו בזמן אתחול ובעת שדרוג, ולכן לתפקיד נדרשות הרשאות ליצור ולשנות טבלאות בסכמת היעד. ראו שדרוגים ו-Postgres.
usernameלאדורס את המשתמש שב-postgres_url
passwordלאאישור מסד הנתונים. הגדירו אותו כאן ולא בתוך postgres_url, כדי שהאישור יישאר מחוץ לכתובת. מקבל כל תו וגובר על אישורים שבכתובת.
max_connectionsלאגודל מאגר החיבורים של Postgres לכל replica. ברירת המחדל 5, שהיא שמרנית וידידותית למסדי נתונים משותפים. כשמגבלות הוצאה מופעלות, ה-gateway מבצע כמה פעולות מסד נתונים לכל בקשת inference, ולכן העלו אותו עבור מסד נתונים ייעודי תחת עומס, בתוך מה שגודל מאגר החיבורים מתיר.
connect_timeout_secondsלאשניות שה-gateway ממתין כשהוא פותח חיבור Postgres. מספר שלם מ-1 עד 60, ברירת מחדל 5. העלו אותו אם ניסיונות חיבור מסתיימים ב-timeout כשמופע gateway חדש עולה. דורש Claude Code v2.1.274 או חדש יותר בשרת ה-gateway. גרסאות מוקדמות יותר מסרבות לעלות כשהמפתח מוגדר.
readiness_grace_secondsלאכמה שניות /readyz ממשיך לדווח ready אחרי ש-Postgres מפסיק לענות. מספר שלם מ-0 עד 3600, ברירת מחדל 0. ראו התנהגות בהשבתה לבחירת ערך. דורש Claude Code v2.1.282 או חדש יותר בשרת ה-gateway. גרסאות מוקדמות יותר מסרבות לעלות כשהמפתח מוגדר.

לפיתוח מקומי, הפנו את postgres_url אל מכולת Postgres חד פעמית, לדוגמה docker run --rm -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust postgres.

#upstreams

upstreams היא רשימה סדורה. ה-gateway מעביר את ה-inference אל ה-upstream הראשון שפותר את המודל המבוקש, ומדלג על כל upstream שרשימת groups שלו משאירה את המפתח בחוץ.

ב-5xx, 429, 401, 403, 404 או timeout ה-gateway מבצע failover אל ה-upstream הבא. שאר 4xx לא, משום שהשגיאות האלה מיוחסות לבקשה ולא ל-upstream. 401 או 403 אומר שה-upstream דחה את האישור שבו השתמש ה-gateway, או מנע ממנו גישה, למשל למודל המבוקש. 404 אומר שה-upstream הזה לא מגיש את המודל המבוקש, כך ש-upstream מאוחר יותר ברשימה עדיין יכול.

אם מגדירים forward_user_identity: true על upstream, 429 שהוא מחזיר לבקשה שנשאה את כתובת האימייל של המפתח לא עובר failover. ראו איך סירוב של מגבלה לכל משתמש מגיע אל המפתח.

Failover על 404 דורש gateway v2.1.198 או חדש יותר. מהדורות מוקדמות יותר החזירו את ה-404 הראשון ללקוח גם כאשר upstream מאוחר יותר ברשימה הגיש את המודל.

כמה upstreams של אותו ספק חייבים להגדיר name: ייחודי.

הלקוחות של Amazon Bedrock, Claude Platform on AWS, Agent Platform של Google Cloud ו-Microsoft Foundry נבנים פעם אחת בעת העלייה, וה-SDK שלהם מרעננים אישורים באופן פנימי, ולכן סיבוב של אישורי ענן לא מחייב הפעלה מחדש. מפתחות API סטטיים של Anthropic ו-bearers נקראים בעת העלייה. ראו Anthropic API.

#הודעות שגיאה של upstream

ה-gateway מחזיר את תגובת השגיאה של upstream אחד, או 502 משלו, לפי האופן שבו ה-upstreams ענו:

  • upstream החזיר סטטוס שה-gateway לא מבצע עליו failover: התגובה של אותו upstream. ה-gateway לא מנסה upstreams נוספים.
  • כל upstream שה-gateway ניסה נכשל באופן שעליו הוא מבצע failover: ה-429 האחרון. כשאף אחד לא החזיר 429, ה-gateway מעדיף, לפי הסדר, את ה-401 או 403 האחרון, את ה-404 האחרון, ואת ה-501 האחרון. כשאף אחד לא החזיר אף אחד מאלה, ה-502 של ה-gateway עצמו, all upstreams failed (N attempted). N סופר את רשומות upstreams שלכם, כולל אלה שדולגו, פחות כל רשומה שרשימת groups שלה משאירה את המפתח בחוץ.

כשה-gateway מחזיר תגובה של upstream, הוא שומר את קוד הסטטוס של ה-upstream. האם הוא שומר את ההודעה של ה-upstream תלוי בספק. גוף השגיאה של upstream מסוג Anthropic API מגיע אל המפתח ללא שינוי.

ה-upstreams של Amazon Bedrock, Claude Platform on AWS, Agent Platform של Google Cloud ו-Microsoft Foundry יכולים לציין את מזהי החשבון, ARN של תפקידים ומזהי פרויקט בטקסט השגיאה. ה-gateway רושם את הטקסט המלא ביומן התפעולי. מה שהמפתח רואה מאותם upstreams תלוי בדחייה:

  • 400 או 413 במעטפת השגיאה הסטנדרטית של Anthropic: ההודעה של ה-upstream עצמו, כגון prompt is too long. Claude Platform on AWS, Agent Platform ו-Microsoft Foundry מחזירים מעטפת זו לדחיות של API המודל.
  • 400 או 413 בצורה של הספק עצמו: token מסוג capability_rejected:. כשה-gateway לא יכול לסווג את הדחייה, upstream rejected the request על 400 או request too large for this upstream על 413.
  • כל סטטוס אחר: ניסוח גנרי לפי סטטוס, כגון upstream rate limit exceeded על 429.

לדוגמה, ה-gateway מחליף את Input is too long for requested model. של Amazon Bedrock ב-capability_rejected: prompt_too_long. Claude Code דוחס אוטומטית על ה-token הזה, כפי שהוא עושה על prompt is too long.

שמירה על הודעת 400 או 413 של upstream ענן, או החלפתה ב-token מסוג capability_rejected:, דורשת gateway v2.1.233 או חדש יותר.

#Anthropic API

ה-upstream המינימלי של Anthropic הוא מפתח API מ-Claude Console:

upstreams:
  - provider: anthropic
    auth:
      api_key: ${ANTHROPIC_API_KEY}
    # OR an OAuth bearer (e.g. a Workload-Identity-Federation-exchanged token):
    #   oauth_token: ${file:/var/run/secrets/anthropic-oauth-token}
    # base_url: https://api.anthropic.com   # default; override for a forward proxy

שתי צורות האישור נבדלות בכותרת שהן שולחות:

  • api_key: שולח x-api-key. סובבו אותו ב-Claude Console ועדכנו את משתנה הסביבה.
  • oauth_token: שולח Authorization: Bearer. השתמשו בצורת ה-bearer כשהארגון מנפיק tokens לזמן קצר במקום מפתחות API לזמן ארוך. ה-bearer נקרא פעם אחת בעת העלייה, ולכן הרענון נעשה על ידי טעינה מחדש של הסוד והפעלה מחדש.

במקום מפתח או bearer סטטי, אפשר להשתמש ב-Workload Identity Federation. צרו כלל federation לפי מדריך Workload Identity Federation, ואז עגנו את ה-OIDC JWT של ה-workload כקובץ, כגון token של projected service account ב-Kubernetes או id-token של פלטפורמת CI. ה-gateway מחליף את ה-JWT ב-bearer לזמן קצר ומרענן אותו אוטומטית. קובץ ה-token נקרא מחדש בכל החלפה, ולכן tokens מוקרנים שסובבו נקלטים בלי הפעלה מחדש.

upstreams:
  - provider: anthropic
    auth:
      federation_rule_id: ${ANTHROPIC_FEDERATION_RULE_ID}
      organization_id: ${ANTHROPIC_ORGANIZATION_ID}
      identity_token_file: /var/run/secrets/anthropic/id-token
      # workspace_id: wrkspc_...       # required if the rule covers >1 workspace
      # service_account_id: svac_...   # optional expected-target check
#כותרות זהות לכל משתמש עבור פרוקסי שאתם מריצים

אפשר להפנות את base_url של upstream עם provider: anthropic אל פרוקסי שאתם מריצים, במקום אל Anthropic API. כדי לומר לפרוקסי הזה איזה מפתח שלח כל בקשה, הגדירו forward_user_identity: true על אותו upstream. הפרוקסי יכול אז לייחס הוצאה לכל מפתח. דורש gateway שמריץ Claude Code v2.1.233 או חדש יותר.

לדוגמה, עבור פרוקסי ב-upstream-gateway.internal.example.com:

upstreams:
  - provider: anthropic
    base_url: https://upstream-gateway.internal.example.com
    auth:
      api_key: ${PROXY_KEY}
    forward_user_identity: true        # default false

ה-gateway מוסיף את הכותרות האלה לכל בקשה שהוא מעביר אל אותו upstream.

כותרתערך
x-litellm-end-user-idכתובת האימייל של המפתח, כשה-IdP סיפק אחת.
x-claude-gateway-user-idה-subject של המפתח ב-IdP, מ-claim בשם sub ב-token.
x-claude-gateway-user-emailכתובת האימייל של המפתח, כשה-IdP סיפק אחת.

כש-token של ה-IdP לא נושא אימייל, ה-gateway שולח רק x-claude-gateway-user-id ומשמיט את שתי כותרות האימייל. אם ה-IdP שם את האימייל ב-claim אחר, הגדירו את oidc.email_claim לאותו claim.

הפרוקסי שלכם לא מקבל את כותרות x-claude-code-* ש-Claude Code שולח, כגון x-claude-code-session-id. ה-gateway לא מעביר אותן לאף upstream, ולכן קבצו בקשות לפי מפתח באמצעות הכותרות בטבלה למעלה.

כשהפרוקסי שלכם עונה 429 לבקשה שנשאה את האימייל של המפתח, ה-gateway מחזיר את התגובה הזו למפתח כפי שהיא, בלי failover אל ה-upstream הבא, כך שתקציב או הגבלת קצב לכל משתמש של הפרוקסי נשמרים. שאר התגובות של הפרוקסי פועלות לפי כללי ה-failover הרגילים. אם token של IdP של מפתח לא נושא אימייל, ה-gateway מעביר את הבקשות שלו בלי כותרות האימייל, ולכן 429 לאחת מהבקשות האלה נספר כקיבולת upstream ועובר failover. לפני v2.1.267 בשרת ה-gateway, כל 429 עבר failover.

הגדירו forward_user_identity רק על upstream ש-base_url שלו הוא פרוקסי שאתם מפעילים. ה-gateway שולח כתובות אימייל של מפתחים אל כל שרת ש-base_url מציין. אם base_url הוא Anthropic API, שזו ברירת המחדל, ה-gateway מסרב לעלות.

[!NOTE]

אם מגדירים forward_user_identity על upstream של Amazon Bedrock, ה-gateway יוצא בעת העלייה עם Unrecognized key(s) in object: 'forward_user_identity'. אם הפרוקסי יושב לפני Bedrock, רשמו אותו כ-upstream עם provider: anthropic. ה-gateway שולח ל-upstream הזה את פורמט Anthropic Messages, ולכן הפרוקסי צריך לתרגם בקשות עבור Bedrock. כדי לציין כל מפתח ל-AWS, ראו ייחוס עלות AWS לכל מפתח.

#Amazon Bedrock

לפריסת Amazon Bedrock בצד הלקוח שהשער מחליף או עומד לפניה, ראו Claude Code על Amazon Bedrock. ה-upstream בצד השער:

upstreams:
  - provider: bedrock
    region: us-east-1
    auth: {}                           # preferred: AWS default credential chain
    # OR explicit credentials:
    # auth:
    #   aws_access_key_id: ${AWS_AKID}
    #   aws_secret_access_key: ${AWS_SK}
    #   aws_session_token: ${AWS_ST}
    # OR a Bedrock API bearer token:
    # auth:
    #   aws_bearer_token: ${AWS_BEARER_TOKEN}
    # Override the bedrock-runtime endpoint for FIPS or VPC-endpoint deployments:
    # base_url: https://bedrock-runtime-fips.us-east-1.amazonaws.com

בלוק auth ריק משתמש בשרשרת האישורים של ברירת המחדל ב-AWS SDK: משתני סביבה, ~/.aws/credentials, תפקיד משימה של ECS, מטא-דאטה של מופע EC2, או IRSA על EKS. בייצור, תנו ל-pod של השער תפקיד IAM במקום להטמיע מפתחות סטטיים בתמונת קונטיינר.

אישורים מפורשים חייבים להיות מלאים: השער נכשל בעלייה כש-aws_access_key_id ו-aws_secret_access_key לא מוגדרים יחד, או כש-aws_session_token מוגדר בלעדיהם. לפני v2.1.207, בלוק auth: חלקי עבר אימות.

הגדרהאיך
הרשאות IAMהעניקו ל-principal של השער את bedrock:InvokeModel ואת bedrock:InvokeModelWithResponseStream גם על ה-ARN של פרופילי ההסקה וגם על ה-ARN של מודלי היסוד שמתחתיהם. לקטלוג המובנה באזורי US: arn:aws:bedrock:<region>:<account>:inference-profile/us.anthropic.* ו-arn:aws:bedrock:*::foundation-model/anthropic.*. העניקו גם את bedrock:CountTokens על ה-ARN של מודלי היסוד. השער משתמש בזה, בלי חיוב, כדי לספור את אסימוני הקלט של בקשה שהלקוח נטש, כך שמגבלות ההוצאה יישארו מדויקות. בלי זה השער חוזר לבקשת Bedrock של אסימון אחד עבור הספירה הזו.
גישה למודלAmazon Bedrock מפעיל גישה למודל כברירת מחדל באזורים מסחריים. השער שנותר ברמת החשבון הוא טופס תרחיש השימוש החד-פעמי של Anthropic: אם אף אחד בחשבון ה-AWS שלכם לא שלח אותו, פתחו את קונסולת Amazon Bedrock, בחרו מודל Anthropic מקטלוג המודלים, והשלימו את הטופס. ראו שליחת פרטי תרחיש שימוש לטופס של AWS Organizations ולהרשאות ששולח הטופס צריך.
EKS (IRSA)צרו תפקיד IAM עם המדיניות שלמעלה ומדיניות אמון לספק ה-OIDC של האשכול שלכם, מוגבלת לחשבון השירות של השער. הוסיפו לחשבון השירות את האנוטציה eks.amazonaws.com/role-arn: arn:aws:iam::<acct>:role/claude-gateway. auth: {} קולט את זה.
ECS / EC2צרפו את תפקיד ה-IAM להגדרת המשימה או לפרופיל המופע. auth: {} קולט את זה.
בכל מקום אחרהעבירו אישורים דרך משתני הסביבה AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY ו-AWS_SESSION_TOKEN, או הגדירו אותם במפורש ב-auth: עם הרחבת ${VAR}
אזורregion: הוא אזור נקודת הקצה של ה-API. פרופילי הסקה בין אזורים מנתבים על פני הגאוגרפיה (US, EU, APAC) בלי קשר לאיזה אזור בחרתם. לאזורים שאינם US או ל-ARN של תפוקה מוקצית, הוסיפו בלוק models: עם מזהי ה-upstream הנכונים.
#החלת guardrail של Amazon Bedrock

כדי להחיל guardrail של Amazon Bedrock על כל בקשת הסקה שהשער שולח דרך upstream של Bedrock, הוסיפו בלוק guardrail ל-upstream הזה. נדרש Claude Code v2.1.281 או חדש יותר בשרת השער.

upstreams:
  - provider: bedrock
    region: us-east-1
    auth: {}
    guardrail:
      id: gr-abc123                    # guardrail ID or full ARN
      version: "1"                     # a published version number, or DRAFT
                                       # keep the quotes: a bare 1 fails at boot

העניקו גם את bedrock:ApplyGuardrail על ה-guardrail ל-principal שחותם על הבקשות של ה-upstream הזה: ה-principal של AWS של השער, או עם assume_role התפקיד ששמו ב-role_arn.

הגדירו guardrail על כל upstream של bedrock או על אף אחד. השער מסרב לעלות על תערובת, כי failover יכול אחרת לשלוח בקשה ל-upstream של Bedrock שאין לו guardrail.

ה-guardrail מכסה רק upstream של Bedrock. אם אתם מפרטים ספק אחר ב-upstreams, השער שולח בקשות לספק הזה בלי ה-guardrail, או מסרב לעלות אם הספק הזה הוא mantle.

כשבקשת /v1/messages שבגוף שלה יש שדה amazon-bedrock-*, כגון amazon-bedrock-guardrailConfig, מגיעה ל-upstream של Bedrock שבו מוגדר guardrail, השער עונה 400 במקום להעביר אותה.

[!WARNING]

כברירת מחדל השער לא מוסיף תגיות קלט לפרומפטים, ולכן מסנן guardrail ש-Amazon Bedrock מחיל רק על קלט מתויג לא רץ על תעבורה דרך השער. כדי להוסיף את התגיות, הגדירו input_tagging. אילו מסננים תלויים בתגיות קלט, ראו תגיות קלט בתיעוד של Amazon Bedrock.

#הוספת תגיות קלט ל-guardrail

כדי שהשער יוסיף את תגיות הקלט שמסנן התקפות הפרומפט של guardrail ב-Amazon Bedrock צריך, הגדירו input_tagging בבלוק guardrail והפעילו מחדש את השער. הגדירו את אותו ערך על כל upstream של bedrock, אחרת השער מסרב לעלות. נדרש Claude Code v2.1.316 או חדש יותר בשרת השער. שער בגרסה שאין בה את המפתח יוצא בעלייה עם Unrecognized key(s) in object: 'input_tagging'.

[!WARNING]

לפי התיעוד של Amazon Bedrock, כל מסנן ב-guardrail מפסיק להעריך תוכן לא מתויג ברגע שבקשה נושאת תגיות קלט. נסו את input_tagging על שער בדיקה לפני שתגדירו אותו על שער שמפתחים משתמשים בו.

input_tagging מקבל אחד מהערכים האלה:

input_taggingאיפה השער מתייג טקסטאחרי שה-guardrail חוסם פרומפט
last_messageהודעות user מאז התשובה האחרונה של Claudeב-Claude Code, הפרומפט הבא יכול לעבור, ו-Claude מקבל אחר כך את הפרומפט החסום כחלק מהשיחה
user_messagesהודעות userגם פרומפטים מאוחרים יותר בסשן יכולים להיחסם, עד שהמפתח מסיר את הפרומפט החסום
all_messagesהודעות user ו-assistantכמו user_messages
all_messages_and_systemפרומפט המערכת וכל הודעה, כולל הודעות מערכת באמצע השיחהכמו user_messages

עם last_message, אם בהודעות user מאז התשובה האחרונה של Claude אין טקסט לתיוג, השער מתייג במקום זאת את הודעות המערכת מאמצע השיחה מאז התשובה הזו. קריאת כלי נחשבת לתשובה.

ההנחיה של Amazon Bedrock למסנן התקפות הפרומפט היא לתייג קלט משתמש כך שפרומפט המערכת לא ייכלל. אם תגדירו all_messages_and_system, מסנן שמסמן את פרומפט המערכת של Claude Code עצמו יכול לחסום בקשות.

הדוגמה למטה מתייגת טקסט בכל הודעת user:

upstreams:
  - provider: bedrock
    region: us-east-1
    auth: {}
    guardrail:
      id: gr-abc123
      version: "1"
      input_tagging: user_messages

הודעות user יכולות להחזיק גם טקסט ש-Claude Code מוסיף, כגון תזכורות מערכת, אז בדקו בשער הבדיקה שבקשות רגילות לא נחסמות.

בבדיקות של Anthropic, סשן מתויג שמר על קריאות מטמון הפרומפט מפרומפט אחד לבא אחריו, והתגיות לא הוסיפו אסימוני קלט.

#מה תגיות הקלט לא מכסות

אף ערך של input_tagging לא עוצר מפתח שמכניס בכוונה טקסט למקום שאליו לא מגיעה תגית. אל תסתמכו על ה-guardrail שיעריך את החלקים האלה של בקשה:

  • תוכן שהשער לא מתייג: הודעות שערך input_tagging שלכם משאיר בחוץ, הגדרות כלים, קלטי קריאות כלים, תמונות ו-PDF, בין היתר. אלא אם הגדרתם all_messages_and_system, גם פרומפט המערכת לא מתויג.
  • תוצאות כלים: אלה מחזיקות את מה שהכלים של Claude מחזירים, כגון תוכן קבצים ודפי אינטרנט. בבדיקות של Anthropic, מסנן מילים לא העריך אותן, עם תגיות או בלעדיהן.

אם חשבון ה-AWS או הארגון שלכם אוכף guardrail, ראו את התיעוד של Amazon Bedrock לגבי האופן שבו ה-guardrail הזה מטפל בתגיות קלט.

#תיעוד איזה מסנן guardrail הופעל

כדי לגלות איזה מסנן guardrail של Amazon Bedrock חסם בקשה של מפתח, הגדירו guardrail_trace: true על ה-upstream של Bedrock, הפעילו מחדש את השער, ובקשו מהמפתח לשלוח את הבקשה שוב. אחר כך מצאו את אירוע guardrail.trace של הבקשה ביומן הביקורת. נדרש Claude Code v2.1.314 או חדש יותר בשרת השער. שער מוקדם יותר מסרב לעלות כשהוא מוצא את guardrail_trace.

upstreams:
  - provider: bedrock
    region: us-east-1
    auth: {}
    guardrail:
      id: gr-abc123
      version: "1"
    guardrail_trace: true              # default false; beside guardrail, not inside it

השער כותב אירוע guardrail.trace, בלי הטקסט שנמצאה לו התאמה, כשמסנן הופעל או כשהפעולה של ה-guardrail היא INTERVENED. מצאו את האירועים של המפתח לפי email או sub. בקשה אחת בזרימה יכולה לייצר כמה אירועים, ואחד מהם יכול לכלול רשימת filters ריקה, אז קראו כל אירוע שיש לו אותו request_id:

שדהמה הוא מחזיק
request_idמזהה הבקשה
sub, emailמזהה המשתמש והאימייל של המפתח
upstreamה-upstream שממנו הגיעה התשובה
actionהפעולה של ה-guardrail, כגון INTERVENED
filtersהמסננים שהופעלו. הרשימה ריקה כש-AWS לא שולח פירוט מסנן
filters[].sideinput או output
filters[].guardrailמזהה ה-guardrail
filters[].policyמדיניות Bedrock והרשימה, כגון contentPolicy.filters או sensitiveInformationPolicy.piiEntities
שדות אחרים ב-filters[]רשומה יכולה לשאת גם שדות כגון action, name, type, confidence, filterStrength, score ו-threshold

האירוע משמיט את הטקסט שמסנן מצא לו התאמה, כולל שדה match במעקב של Bedrock. מפתחים לא מקבלים את נתוני המעקב של Bedrock, כי השער מסיר אותם מכל תשובה, בזרימה או לא.

אם לקוח שולח שדה amazon-bedrock-* בגוף בקשת /v1/messages, השער עונה 400 על upstream שמגדיר guardrail_trace.

#Bedrock בחשבון AWS אחר

הגדירו assume_role על upstream של Bedrock והשער משתמש בזהות ה-AWS שלו רק כדי לקרוא ל-sts:AssumeRole על תפקיד שאתם מציינים, שיכול להיות בחשבון AWS שונה מזה של השער. כל בקשת Bedrock מה-upstream הזה חתומה באישורים של שעה ש-STS מחזיר, כך שאף מפתח גישה ארוך טווח לא עובר בין חשבונות.

נדרש שער שמריץ Claude Code v2.1.281 או חדש יותר. שער מוקדם יותר מסרב לעלות כשהוא מוצא את המפתח.

upstreams:
  - name: bedrock-isolated
    provider: bedrock
    region: us-east-1
    auth: {}                           # the gateway's own role: it only calls STS
    assume_role:
      role_arn: arn:aws:iam::222222222222:role/claude-gateway-bedrock
      # external_id: ${BEDROCK_ROLE_EXTERNAL_ID}   # when the role's trust policy requires one

בלוק assume_role מקבל שלושה מפתחות:

מפתחמשמעות
role_arnתפקיד ה-IAM שהשער מקבל על עצמו, כ-ARN מסוג arn:aws:iam:: או arn:aws-us-gov:iam::. תנו לו את הרשאות Bedrock שה-upstream הזה צריך, כולל bedrock:CountTokens, ובנוסף bedrock:ApplyGuardrail כשה-upstream מגדיר guardrail.
external_idאופציונלי. נשלח כמזהה החיצוני בכל קריאה ל-sts:AssumeRole. הגדירו אותו כשמדיניות האמון של התפקיד דורשת אחד, וצטטו אותו אם הוא כולו ספרות.
session_nameאופציונלי. email או sub נותנים לכל מפתח סשן משלו: ראו שיוך עלויות AWS לפי מפתח. כשלא מוגדר, כל בקשה משתמשת בסשן אחד בשם claude-apps-gateway.

מדיניות האמון של התפקיד מציינת את ה-principal של השער עצמו, כגון תפקיד IRSA או תפקיד משימת ECS שלו. ה-principal הזה צריך sts:AssumeRole על התפקיד, ובלי הרשאת Bedrock משלו. השמיטו את Condition אם לא הגדרתם external_id.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "AWS": "arn:aws:iam::111111111111:role/claude-gateway" },
    "Action": "sts:AssumeRole",
    "Condition": { "StringEquals": { "sts:ExternalId": "your-external-id" } }
  }]
}
  • אם STS מסרב או לא נגיש, השער לא שולח את הבקשה עם האישורים של ה-upstream עצמו. הוא רושם ביומן את שגיאת STS עם מה לבדוק, ואז מנסה את ה-upstream הבא שפירטתם. הודעות שגיאה של upstream מכסות את מה שהלקוח מקבל כשאף upstream לא מצליח. upstream מאוחר יותר בלי assume_role ישרת את הבקשה עם האישורים שלו, אז פרטו אחד רק אם זה מה שאתם רוצים.
  • השער קורא לנקודת הקצה האזורית של STS, sts.<region>.amazonaws.com, שהרשת שלו חייבת להגיע אליה. לנקודת הקצה של FIPS, הגדירו AWS_USE_FIPS_ENDPOINT=true בסביבה של השער ולא use_fips_endpoint בקובץ תצורה של AWS.
  • assume_role צריך אישורי מקור של SigV4: השער מסרב לעלות כשהוא מוגדר לצד aws_bearer_token.
  • בלי רשימת groups, כל מפתח שהשער מכניס יכול להשתמש ב-upstream הזה. כדי להגביל אילו מודלים מפתח יכול להשתמש בהם, הגדירו availableModels במדיניות managed.
  • כדי שמודל שמגיע דרך התפקיד לא יגיע גם מחשבון אחר, תנו לו מזהה מותאם אישית שמפת upstream_model שלו כוללת רק את שם ה-upstream הזה. למזהה כזה השער מדלג על כל upstream אחר, כך שגם הבקשה וגם ספירת האסימונים של בקשה שבוטלה לא יכולות לעבור ב-failover לחשבון אחר.
  • בקשה לשם מודל מובנה עדיין יכולה להגיע ל-upstream הזה, והשער חותם עליה באותו תפקיד. פרטו את ה-upstream הזה אחרון, אלא אם החשבון שלו צריך גם לשרת את המודלים האלה.

הדוגמה הזו נותנת למודל אחד מזהה מותאם אישית שרק ה-upstream המבודד משרת:

models:
  - id: restricted-claude-opus-4-8      # a custom id, not a built-in model name
    upstream_model:
      bedrock-isolated: us.anthropic.claude-opus-4-8   # the only upstream that serves it
#שיוך עלויות AWS לפי מפתח

כברירת מחדל השער חותם על כל בקשת Bedrock באישור אחד, כך ש-AWS רואה את הבקשות של כל המפתחים תחת principal אחד של IAM. הוסיפו session_name: email ל-assume_role והשער קורא ל-sts:AssumeRole פעם אחת לכל מפתח בכל שעה, כששם הסשן מוגדר לאימייל של המפתח הזה, וחותם על הבקשות שלו באישורים שהוחזרו, כך שהבקשות של כל מפתח מגיעות ל-AWS תחת סשן assumed-role משלו. התפקיד יכול להיות בחשבון של השער עצמו.

נדרש שער שמריץ Claude Code v2.1.281 או חדש יותר. שיוך עלויות ב-AWS מכסה את תפקיד ה-IAM ואיפה החיוב של AWS מציג את הסשנים.

upstreams:
  - provider: bedrock
    region: us-east-1
    auth: {}                           # the gateway's own role: it only calls STS
    assume_role:
      role_arn: arn:aws:iam::123456789012:role/claude-gateway-bedrock-user
      session_name: email              # or sub

session_name בוחר איזו טענה מאומתת הופכת ל-RoleSessionName של AWS: email או sub. השער כותב כל תו שאינו אותיות ASCII, ספרות ו-_+,.@- כהקסדצימלי =XX לכל בית UTF-8, ומקצר תוצאה ארוכה מ-64 תווים לקידומת ועוד גיבוב, כך ששם הסשן של כל מפתח נשאר תקין וייחודי. בקשה ממפתח שהאסימון שלו חסר את הטענה לא נשלחת דרך ה-upstream הזה, ויומן המפעיל אומר לעבור ל-sub או להגדיר oidc.email_claim.

מפתח פעיל עולה קריאת STS אחת בשעה לכל replica של השער, ובקשות ראשונות מקבילות חולקות קריאה אחת.

השער גם מבצע קריאה אחת משלו על התפקיד הזה: ספירת האסימונים של בקשה שהלקוח נטש, כך שמגבלות ההוצאה יישארו מדויקות. הספירה הזו ובקשת הגיבוי של אסימון אחד חתומות על ידי הסשן המשותף claude-apps-gateway, כך ש-AWS מייחס את הגיבוי ל-claude-apps-gateway ולא למפתח.

לשיוך קפדני לפי מפתח, הגדירו assume_role עם session_name על כל upstream של Bedrock שאתם מפרטים. upstream בלי זה חותם על הבקשות שהוא משרת באישורים שלו.

#נקודת הקצה Mantle של Amazon Bedrock

ספק mantle שולח הסקה אל נקודת הקצה Mantle של Amazon Bedrock. הוא דורש Claude Code v2.1.283 או חדש יותר בשרת השער. גרסאות שער מוקדמות יותר דוחות אותו בעת האתחול, לכן שדרגו כל עותק לפני שמוסיפים אותו.

הדוגמה למטה שמה את Mantle ראשון, עם upstream של Amazon Bedrock אחריו כדי לשרת כל מודל שהשדה models משאיר בחוץ:

upstreams:
  - provider: mantle
    region: us-east-1
    models: [claude-opus-4-7, claude-haiku-4-5]   # required
    auth: {}                           # AWS default credential chain
  - provider: bedrock
    region: us-east-1
    auth: {}

הטבלה למטה מפרטת את השדות הייחודיים ל-upstream מסוג mantle.

שדהחובהתיאור
regionכןאזור AWS. השער גוזר ממנו את נקודת הקצה כ-https://bedrock-mantle.<region>.api.aws/anthropic.
modelsכןהמודלים שהחשבון שלכם ב-AWS קיבל הרשאה אליהם ב-Mantle, בשמות שבהם הלקוחות שולחים אותם, למשל claude-haiku-4-5. רק אלה הולכים ל-upstream הזה, וכל מודל אחר מדלג אל הבא.
authלאמקבל את אותם מפתחות כמו בלוק auth של ה-upstream Amazon Bedrock, לפי אותם כללים.
assume_roleלאהתפקיד שדרכו עוברות הבקשות של ה-upstream הזה, עם אותם מפתחות כמו ב-upstream מסוג bedrock, כולל session_name עבור שיוך לכל מפתח. תנו לתפקיד את פעולות ה-IAM של Mantle. דורש שער שמריץ Claude Code v2.1.318 או חדש יותר. שער מוקדם יותר יוצא בעת ההפעלה עם Unrecognized key(s) in object: 'assume_role'.
base_urlלאדריסת נקודת הקצה הנגזרת. השאירו את הנתיב /anthropic בסוף.

העניקו לזהות ה-AWS של ה-upstream את פעולות ה-IAM של Mantle עצמו להסקה ולספירת אסימונים, שאותן מפרט Use the Mantle endpoint.

עבור מזהה מודל של Mantle שהשער לא מכיר, הוסיפו רשומה לבלוק models: ברמה העליונה, ש-upstream_model שלה ממפה את השם של ה-upstream הזה אל המזהה הזה. אחר כך שימו גם את ה-id של הרשומה הזו בשדה models של ה-upstream הזה.

ההגדרות guardrail ו-assume_role של upstream מסוג bedrock לא חלות על הבקשות ש-Mantle מגיש:

  • guardrail: השער לא מחיל Bedrock guardrail על בקשות שהוא שולח אל Mantle, ולכן הוא מסרב להתחיל כש-upstream מסוג mantle רשום בזמן ש-upstream כלשהו מסוג bedrock מגדיר guardrail.
  • assume_role: הגדירו אותו על ה-upstream מסוג mantle עצמו. בלעדיו, בקשות ש-Mantle מגיש נשלחות עם פרטי ההתחברות של auth של ה-upstream מסוג mantle עצמו.

למשמעות תגובות השגיאה של Mantle עצמו, ראו Mantle endpoint errors.

#Claude Platform on AWS

Claude Platform on AWS מגיש את ה-API הרשמי של Anthropic על תשתית AWS בכתובת aws-external-anthropic.<region>.api.aws. הוא משתמש במזהי מודלים רשמיים, מכבד כותרות anthropic-beta כפי שנשלחו, ומגיש את count_tokens, כך שאף אחת מההמרות הייחודיות ל-Bedrock לא חלה. ספק anthropicAws דורש Claude Code v2.1.198 או חדש יותר. גרסאות שער מוקדמות יותר דוחות אותו בעת האתחול.

לפריסה בצד הלקוח של אותה פלטפורמה, ראו Claude Code on Claude Platform on AWS. ה-upstream בצד השער:

upstreams:
  - provider: anthropicAws
    region: us-east-1
    workspace_id: wrkspc_...
    auth:
      api_key: ${ANTHROPIC_AWS_API_KEY}   # sent as x-api-key
    # OR SigV4 via the AWS default credential chain:
    # auth: {}
    # OR explicit SigV4 credentials:
    # auth:
    #   aws_access_key_id: ${AWS_ACCESS_KEY_ID}
    #   aws_secret_access_key: ${AWS_SECRET_ACCESS_KEY}
    # Override the derived endpoint:
    # base_url: https://aws-external-anthropic.us-east-1.api.aws

הפלטפורמה רצה בחשבון AWS נפרד מ-Amazon Bedrock וחותמת בקשות SigV4 עבור שם השירות שלה, aws-external-anthropic, כך שתפקיד IAM שמוגבל ל-Bedrock לא מאשר אותה. מפתח API ב-auth.api_key מקבל עדיפות כשגם פרטי התחברות של SigV4 מוגדרים. בלוק auth ריק משתמש בשרשרת פרטי ההתחברות ברירת המחדל של AWS SDK, אותה שרשרת שבה משתמש ה-upstream Amazon Bedrock.

שדהחובהתיאור
regionכןאזור AWS, אותיות קטנות, ספרות ומקפים. השער גוזר ממנו את נקודת הקצה כ-https://aws-external-anthropic.<region>.api.aws.
workspace_idכןנשלח ככותרת בכל בקשה. הפלטפורמה דורשת אותו
auth.api_keyלאמפתח API לפלטפורמה, נשלח כ-x-api-key. זה לא אסימון bearer: שני מצבי האימות הם מפתח API או SigV4.
auth.aws_access_key_id / auth.aws_secret_access_keyלאפרטי התחברות מפורשים של SigV4. הגדרת אחד בלי השני נכשלת בעת האתחול. auth.aws_session_token מתקבל לצד שניהם.
base_urlלאדריסת נקודת הקצה הנגזרת

מכיוון שהפלטפורמה פותרת מזהי מודלים רשמיים, הקטלוג המובנה מנתב אליה בלי בלוק models:. כשאתם אוצרים רשימת models:, מפתחו את הרשומה ב-anthropicAws: עם המזהה הרשמי.

#Google Cloud Agent Platform

להגדרה המקבילה בצד הלקוח, ראו Claude Code on Google Cloud. ה-upstream בצד השער:

upstreams:
  - provider: vertex
    region: us-east5
    project_id: example-prod
    auth: {}                           # preferred: Application Default Credentials
    # OR a service account key file:
    # auth: { service_account_json: /secrets/sa.json }
    # Override the aiplatform endpoint for Private Service Connect:
    # base_url: https://us-east5-aiplatform.p.googleapis.com

בלוק auth ריק משתמש ב-Application Default Credentials: GOOGLE_APPLICATION_CREDENTIALS, מטא-נתונים של GCE, או GKE Workload Identity. קבצי מפתח JSON של חשבון שירות נתמכים אבל לא מומלצים. השתמשו ב-Workload Identity או צרפו חשבון שירות למופע GCE או Cloud Run.

הגדירו region: global כדי להשתמש ב-נקודת הקצה הגלובלית של Agent Platform של Google Cloud במקום בנקודת קצה אזורית. Google מנתבת אז כל בקשה לאזור זמין, כך שאין צורך לעקוב אחרי זמינות מודל לפי אזור. הגדרת אזור מסוים מצמידה כל בקשה אליו.

הגדרהאיך
הרשאות IAMהעניקו לחשבון השירות של השער את roles/aiplatform.user בפרויקט, או תפקיד מותאם עם aiplatform.endpoints.predict. הפעילו את ה-API של Agent Platform של Google Cloud (aiplatform.googleapis.com).
גישה למודליםב-Model Garden, הפעילו את מודלי Claude עבור הפרויקט שלכם. הם מתפרסמים לאזורים מסוימים. בדקו בכרטיס המודל את האזורים הנתמכים.
GKE (Workload Identity)קשרו חשבון שירות של GCP לחשבון השירות של Kubernetes של השער, וסמנו את ה-KSA ב-iam.gke.io/gcp-service-account: claude-gateway@<proj>.iam.gserviceaccount.com. auth: {} קולט אותו.
Cloud Run / GCEהגדירו את חשבון השירות של השירות לחשבון עם roles/aiplatform.user. auth: {} קולט אותו.
בכל מקום אחרauth: { service_account_json: /secrets/sa.json }, הנתיב לקובץ מפתח JSON שמורכב כסוד. השדה מקבל נתיב קובץ, לא את תוכן המפתח, כך שאין הרחבה של ${file:…}.

#Microsoft Foundry

לפריסת Microsoft Foundry בצד הלקוח, ראו Claude Code on Microsoft Foundry. ה-upstream בצד השער:

upstreams:
  - provider: foundry
    resource: example-foundry              # https://example-foundry.services.ai.azure.com
    auth: { use_azure_ad: true }        # preferred: DefaultAzureCredential / Managed Identity
    # OR an API key:
    # auth:
    #   api_key: ${FOUNDRY_API_KEY}

use_azure_ad: true נפתר דרך DefaultAzureCredential: Managed Identity ב-AKS, ב-ACI או ב-App Service, Azure CLI, או פרטי התחברות מסביבה. מפתחות API עובדים אבל הם ברמת הפרויקט ולא מתחלפים אוטומטית. נקודת הקצה של Microsoft Foundry נגזרת מ-resource:. הגדירו את base_url האופציונלי כדי לדרוס אותה עבור עננים ריבוניים כמו Azure Government.

הגדרהאיך
RBACהעניקו לזהות השער את Azure AI User או Cognitive Services User על משאב Microsoft Foundry
פריסותMicrosoft Foundry משתמש בשמות פריסה שהמנהל בחר, לא במזהי מודל קנוניים. הוסיפו בלוק models: שממפה כל מזהה קנוני לשם הפריסה שלכם.
AKS (workload identity)אחדו User-Assigned Managed Identity עם מנפיק ה-OIDC של האשכול וקשרו אותו לחשבון השירות של השער. use_azure_ad: true קולט אותו דרך WorkloadIdentityCredential.
ACI / App Serviceהפעילו managed identity שמוקצה על ידי המערכת או על ידי המשתמש על המשאב. use_azure_ad: true קולט אותו.
בכל מקום אחרauth: { api_key: "${FOUNDRY_API_KEY}" }. שימו ${…} במרכאות בתוך { }.

#כותרות סטטיות בבקשות upstream

כדי להוסיף כותרות קבועות לבקשות שהשער שולח ל-upstream אחד, הגדירו headers: על אותו upstream. השתמשו בזה כשפרוקסי שאתם מריצים לפני הספק מנתב או משייך תעבורה לפי כותרת.

headers: דורש Claude Code v2.1.277 או חדש יותר בשרת השער. שער מוקדם יותר מסרב להתחיל כשהוא מוצא את המפתח. שדרגו כל עותק לפני שאתם מוסיפים את המפתח, והסירו את המפתח לפני שאתם חוזרים לגרסה מוקדמת יותר.

הכותרות הולכות לשרת ש-base_url מציין, או לנקודת הקצה של הספק עצמו כש-base_url לא מוגדר. גם הספק מקבל אותן, אלא אם הפרוקסי שלכם מסיר אותן.

הדוגמה הזו מגיעה ל-upstream של provider: vertex דרך פרוקסי ב-upstream-proxy.internal.example.com. היא מגדירה את הכותרת x-source שהפרוקסי קורא, ושולחת אסימון ממשתנה הסביבה PROXY_TOKEN כ-x-proxy-token:

upstreams:
  - provider: vertex
    region: us-east5
    project_id: example-prod
    base_url: https://upstream-proxy.internal.example.com
    auth: {}
    headers:
      x-source: claude-apps-gateway
      x-proxy-token: ${PROXY_TOKEN}

הערכים הם טקסט ASCII להדפסה בלי רווח באף אחד מהקצוות. שימו מספר, true או false במרכאות כדי ש-YAML יקרא אותם כטקסט.

כדי להשאיר סוד מחוץ לקובץ התצורה, השתמשו ב-הרחבת סודות כדי לטעון את הערך ממשתנה סביבה עם ${VAR} או מקובץ עם ${file:/path}. ${VAR} שנפתר לערך ריק עוצר את השער מלהתחיל.

headers: עובד בכל ספק, וכל upstream שולח רק את שלו.

לא כל בקשה שהשער שולח ל-upstream נושאת אותן:

הבקשה שהשער שולח ל-upstream הזהנושאת headers:
/v1/messages, עם או בלי הזרמה, וגם /v1/messages/count_tokensכן
בקשה שעברה failover מ-upstream אחרכן, רק headers: של ה-upstream הזה
קריאת CountTokens של Amazon Bedrock עבור בקשה שהלקוח נטשלא
החלפת האסימון של Workload Identity Federationלא

ב-upstream של Amazon Bedrock או של Claude Platform on AWS שחותם בקשות עם AWS SigV4, הכותרות האלה הן חלק מהחתימה, כך שהפרוקסי שלכם חייב להעביר אותן בלי שינוי.

אם אתם משתמשים בשם שהשער שומר, הוא מסרב להתחיל, ושגיאת ההפעלה מציינת את הכותרת. שמות שמורים כוללים:

  • authorization ו-x-api-key
  • host, content-type ו-user-agent
  • כל שם שמתחיל ב-anthropic-, x-goog-, x-amz- או x-amzn-

#upstreams מרובים

אותו ספק יכול להופיע יותר מפעם אחת עם name: נפרד. זה מכסה אזורים שונים, חשבונות שונים דרך שרשראות פרטי התחברות שונות, provisioned throughput לעומת לפי דרישה, וגיבוי בין ספקים.

השער מנסה upstreams לפי הסדר. 5xx, 429, 401, 403, 404, פסקי זמן, ונקודת קצה חסרה (501) עוברים failover. שאר 4xx לא.

429 הוא קיבולת לכל upstream, כך שמיצוי של provisioned throughput (PT) עובר failover לפי דרישה. אם אתם מגדירים forward_user_identity: true על upstream, 429 לבקשה שנשאה את הדוא"ל של המפתח הוא סירוב לכל משתמש במקום זאת, ולא עובר failover.

בקשה עוברת מעבר ל-upstream רק במקרים האלה:

  • ה-upstream נכשל
  • ה-upstream לא מגיש את המודל המבוקש
  • ל-upstream יש רשימת groups שמשאירה את המפתח בחוץ

השער לא שומר תיעוד של upstreams שנכשלו, כך שכל עוד upstream מושבת, כל בקשה שמגיעה אליו עדיין מנסה אותו וממתינה שייכשל לפני שהיא ממשיכה.

השער ממתין כך להתחלת תגובה:

  • upstreams של provider: anthropic: timeouts.upstream_ttfb_ms, 120 שניות כברירת מחדל
  • ספקים אחרים: עד שעה. כדי לקצר את ההמתנה הזו לבקשות הזרמה, הגדירו timeouts.upstream_ttfb_ms בשער v2.1.295 או חדש יותר. בקשות מודל בלי הזרמה ממתינות עד שעה בכל מקרה

404 הוא זמינות מודל לכל upstream, כך ש-upstream שלא הפעיל מודל לא חוסם upstream מאוחר יותר שמגיש אותו. upstream שלא יכול לפתור את המודל המבוקש מדולג בלי הלוך ושוב ברשת.

הדוגמה הזו מנתבת הקצאת provisioned throughput של Amazon Bedrock ראשונה, גולשת לפי דרישה ולחשבון שני, ונופלת ל-API של Anthropic אחרון:

upstreams:
  # Primary: provisioned throughput in your home region.
  - name: bedrock-pt
    provider: bedrock
    region: us-east-1
    auth: {}
  # Overflow: on-demand cross-region.
  - name: bedrock-od
    provider: bedrock
    region: us-west-2
    auth: {}
  # Different account: a separate Bedrock allotment via static keys.
  - name: bedrock-acct2
    provider: bedrock
    region: us-east-1
    auth:
      aws_access_key_id: ${ACCT2_AKID}
      aws_secret_access_key: ${ACCT2_SK}
  # Last resort: direct Anthropic API.
  - name: anthropic-fallback
    provider: anthropic
    auth:
      api_key: ${ANTHROPIC_API_KEY}

# Per-upstream model IDs are keyed on the upstream's `name:`.
models:
  - id: claude-opus-4-8
    label: Claude Opus 4.8
    upstream_model:
      bedrock-pt: arn:aws:bedrock:us-east-1:111111111111:provisioned-model/abcdef
      bedrock-od: us.anthropic.claude-opus-4-8
      bedrock-acct2: us.anthropic.claude-opus-4-8
      anthropic-fallback: claude-opus-4-8
מנוףאיך
אזורים שוניםupstream אחד של Amazon Bedrock לכל אזור, כל אחד עם region: משלו. עם auto_include_builtin_models: true פרופילי ההסקה בין אזורים מנותבים אוטומטית. לפריסות שמוצמדות לאזור השתמשו בבלוק models:.
חשבונות שוניםupstream אחד של Amazon Bedrock לכל חשבון. שרשרת ברירת המחדל (auth: {}) משתמשת בזהות של ה-pod. לחשבון שני, הוסיפו assume_role כדי להגיע אליו עם פרטי התחברות קצרי חיים, או הגדירו פרטי התחברות מפורשים או אסימון bearer ב-auth:.
צוותים שוניםתנו ל-upstream של כל צוות רשימת groups, כך שרק מפתחים בקבוצות ה-IdP האלה מגיעים אליו. ראו Send each team to its own upstream.
Provisioned throughputמפו את המודל ל-ARN של provisioned throughput ב-models: עבור השם של אותו upstream. upstreams אחרים שומרים את מזהה לפי הדרישה, כך שקיבולת ה-PT ממוצה לפני failover.
נקודות קצה של VPC / FIPSהגדירו base_url: על ה-upstream לכתובת נקודת הקצה של ה-VPC או של FIPS
ניתוב לפי מודלid של מודל מותאם, כזה שאינו מודל Claude מובנה, מדלג על ה-upstreams שנעדרים ממפת upstream_model: שלו. upstream עם רשימת models, ש-upstream מסוג mantle חייב שתהיה לו, מנוסה רק עבור המודלים האלה.
ניתוב מודל מובנהב-upstream בלי רשימת models או groups, השער מנסה מודלים מובנים לפי הסדר ומשתמש במזהה ברירת המחדל של הספק במקום שבו למפת upstream_model: אין רשומה. למודל מובנה שלספק יש עבורו מזהה ברירת מחדל, המפה משנה איזה מזהה ה-upstream מקבל ולא אם הוא מנוסה. upstream שדוחה את המזהה פועל לפי אותם כללי failover כמו כל שגיאת upstream אחרת.

failover בין ספקי ענן, או אל ה-API הישיר של Anthropic, משנה איזה הסכם, גאוגרפיה ותנאים אחרים חלים על הבקשה.

ה-CLI מחיל את אותו שער תכונות על שערים בלי קשר לאיזה upstream מגיש בקשה נתונה, כך שכברירת מחדל failover לא שולח שדה גוף ש-upstream היה דוחה. אם אתם מגדירים את TTL המטמון של שעה במדיניות, הוא הולך לכל upstream ברשימה, לכן הגדירו אותו רק אם כולם מקבלים אותו.

#שליחת כל צוות ל-upstream משלו

כדי לשלוח את הבקשות של כל צוות לחשבון AWS או לפרויקט Google Cloud משלו, רשמו upstream אחד לכל צוות ותנו לכל אחד רשימת groups. רק מפתחים בקבוצת IdP שברשימה מגיעים ל-upstream הזה, בניסיון הראשון וב-failover. כל ספק מקבל groups. נדרש Claude Code v2.1.314 או חדש יותר בשרת ה-gateway.

הדוגמה הזו נותנת לקבוצות payments-eng ו-search-eng חשבון AWS לכל אחת, ומוסיפה upstream בלי רשימת groups שכל מפתח יכול להשתמש בו:

upstreams:
  - name: bedrock-payments
    provider: bedrock
    region: us-east-1
    auth: {}
    assume_role:
      role_arn: arn:aws:iam::111111111111:role/claude-gateway-bedrock
    groups: [payments-eng]
  - name: bedrock-search
    provider: bedrock
    region: us-east-1
    auth: {}
    assume_role:
      role_arn: arn:aws:iam::222222222222:role/claude-gateway-bedrock
    groups: [search-eng]
  - name: bedrock-shared               # no groups: open to everyone, so listed last
    provider: bedrock
    region: us-east-1
    auth: {}

עם תצורת הדוגמה, הבקשות של כל מפתח מתחילות ב-upstream הראשון בשורה שלו ועוברות לבא ב-failover:

קבוצות המפתחUpstreams, לפי הסדר
payments-engbedrock-payments, ואז bedrock-shared
search-engbedrock-search, ואז bedrock-shared
payments-eng ו-search-engbedrock-payments, ואז bedrock-search, ואז bedrock-shared
אף אחת מהןbedrock-shared

כש-upstream של צוות דוחה את המודל המבוקש עם 403, ה-gateway מנסה את ה-upstream הבא בשורה של אותו צוות שמגיש את המודל. כדי להשאיר את הצוות על upstream אחד, תנו לכל upstream רשימת groups, וודאו שאף upstream אחר לא מציין קבוצה שהמפתחים של הצוות נמצאים בה. לצוות הזה אין אז failover, ובקשות ממפתחים שלא נמצאים באף קבוצה שברשימה נכשלות עם 400.

כדי להביא כל מפתח ל-upstream שאתם מתכוונים אליו, כתבו רשומות שתואמות בדיוק ושימו upstreams פתוחים בסוף:

  • רשומות: כתבו כל קבוצה בדיוק כפי שה-IdP שולח אותה ב-groups claim, שגם match.groups קורא. ה-gateway מסרב להתחיל כשהוא מוצא רשימה ריקה או רשומה ריקה. הוא לא בודק רשומה מול ה-IdP, ולכן רשומה שלא תואמת לאף אחד לא מעלה אזהרה.
  • סדר: שימו upstream שאין לו רשימת groups בסוף. הוא משרת את כולם, ולכן אם הוא מופיע מוקדם יותר הוא לוקח את הבקשות של צוות לפני ה-upstream של הצוות עצמו.

[!WARNING]

gateway מוקדם מ-v2.1.314 מסרב להתחיל כשהוא מוצא groups, אז שדרגו כל replica לפני שאתם מוסיפים אותו.

לפני rollback, הסירו כל upstream שיש לו רשימת groups וכל מפתח upstream_model או pricing override שמציין אותו, והשאירו לפחות upstream אחד. כשרק מפתח groups הוסר, ה-upstream הזה פתוח לכל מפתח. מפתח או override שעדיין מציין upstream שהוסר עוצר את ה-gateway מהתחלה, עם references unknown upstream.

#מה קורה כשמפתח לא נמצא באף קבוצה שברשימה

אם לכל upstream יש רשימת groups, מפתח שלא נמצא באף אחת מהקבוצות האלה רואה את השגיאה הזו, וה-gateway לא פונה לאף ספק:

API Error: 400 you aren't in a group that can use this gateway. Ask your administrator to add you to one

הוסיפו את המפתח לקבוצה שברשימה ב-IdP, או הוסיפו upstream בלי רשימת groups.

ה-gateway קורא שוב את הקבוצות של מפתח בכל רענון token. אם ה-IdP משמיט קבוצות מרענון, למפתח אין אז אף קבוצה:

  • oidc.allowed_groups מוגדר: ה-gateway מסרב לרענון, והסשן מסתיים
  • אחרת, ל-upstream אין רשימת groups: הבקשות של המפתח עוברות אליו
  • אחרת, לכל upstream יש רשימת groups: הבקשות של המפתח נכשלות עם השגיאה הזו

אם נקודת הקצה userinfo של ה-IdP מחזירה את ה-groups claim ו-oidc.google_groups לא מוגדר, הגדירו את oidc.userinfo_fallback ל-true כדי למלא את הקבוצות משם.

#מקטעים אופציונליים

#admin

אופציונלי. מפעיל את /v1/organizations/spend_limits, שמשקף את Admin API הציבורי של Anthropic, ואכיפת הוצאה לכל מפתח ב-/v1/messages. ראו Spend limits לאופן קביעת תקרות ואכיפתן. המקטע הזה מכסה את המפתחות ב-gateway.yaml שמפעילים את התכונה ומכוונים אותה.

admin:
  # Named static API keys for the admin endpoints, sent as x-api-key.
  # The id appears in the audit log as admin-key:<id> so each key is
  # attributable. Array for rotation: add the new key, roll clients,
  # remove the old.
  write_keys:
    - { id: terraform, key: "${GATEWAY_ADMIN_WRITE_KEY_TF}" }
    - { id: ci,        key: "${GATEWAY_ADMIN_WRITE_KEY_CI}" }
  read_keys:
    - { id: reporting, key: "${GATEWAY_ADMIN_READ_KEY}" }
  # IdP groups granted full admin via the normal gateway JWT (no API key).
  admin_groups: [platform-finops]
  blocked_message: request an increase at https://go.example.com/claude-limits
שדהנדרשתיאור
write_keysלאמערך של {id, key}. x-api-key שתואם לאחד מאלה יכול לרשום, להגדיר ולמחוק מגבלות הוצאה. ערכי המפתח חייבים להיות באורך 32 תווים לפחות. ערכי id חייבים להיות ייחודיים בין read_keys ו-write_keys.
read_keysלאמערך של {id, key}. לקריאה בלבד: כל נקודת קצה GET, כולל רישום תקרות, שליפת אחת לפי ID, וקריאה של /effective ו-/audit.
admin_groupsלאשמות קבוצות IdP. JWT של ה-gateway שה-claim groups שלו כולל אחת מאלה מקבל גישת admin מלאה, קריאה וכתיבה, ומתועד בביקורת כ-oidc:<sub>. השתמשו בזה למנהלים אנושיים. השתמשו במפתחות API למכונות. רשומה ריקה ברשימה הזו עוצרת את ה-gateway באתחול. ראו Matcher values that stop the gateway at boot.
blocked_messageלאמצורף כלשונו ל-429 billing_error שמפתח חסום רואה. כתבו את כל ההנחיה, כגון URL או ערוץ Slack. כשהשדה לא מוגדר, ה-gateway שולח רק את הודעת ברירת המחדל. ראו How enforcement works.
audit_retention_daysלאברירת מחדל 365. שורות admin_audit ישנות יותר מנוקות.
spend_retention_monthsלאברירת מחדל 13. שורות מונה spend ישנות מזה מנוקות. ברירת המחדל שומרת שנה מלאה ועוד החודש החלקי הנוכחי לדיווח משנה לשנה.
identity_retention_daysלאברירת מחדל 90. TTL של נראה לאחרונה לשורות principal_emails, שמחזיקות את האימייל, שם התצוגה והקבוצות של כל מפתח (PII). קצר במכוון משמירת ההוצאה, כדי שזהות שההקצאה שלה בוטלה תתיישן ותצא, בזמן שמוני ההוצאה האנונימיים שלה נשארים.
group_limit_modeלאmin (ברירת מחדל) או max. כשמפתח נמצא בכמה קבוצות עם תקרות, min אוכף את המגבילה ביותר ו-max את הפחות מגבילה. בשימוש גם באכיפה וגם ב-/effective.

#enforcement

בלוק enforcement שולט באופן שבו בדיקות מגבלת הוצאה מתנהגות כשהאחסון לא זמין.

שדהנדרשתיאור
fail_closed_on_errorלאברירת מחדל false. אכיפת ההוצאה נכשלת במצב fail open בהשבתת Postgres, כך שההסקה נשארת פעילה. הגדירו true כדי fail closed: מפתחים מעל התקרה נחסמים, וכך גם כל השאר אם האחסון לא נגיש. נדרש בלוק admin:: אכיפת הוצאה רצה רק כש-admin מוגדר, וה-gateway מסרב להתחיל אם מגדירים את זה ל-true בלי בלוק כזה.

#pricing

בלוק pricing אומר למד ההוצאה מה לחייב במקום מחיר המחירון ב-USD, כדי שתקרות ו-/effective ישקפו את התעריפים החוזיים שלכם. הסכומים נשארים ב-USD ונשארים אומדן, לא חשבונית. שתי דרישות מוקדמות:

  • Claude Code v2.1.227 או חדש יותר בשרת ה-gateway. גרסאות מוקדמות יותר דוחות את המפתח הלא מוכר באתחול.
  • בלוק admin: או, ב-v2.1.268 או חדש יותר, בלוק managed: עם לפחות מדיניות אחת. ה-gateway מסרב להתחיל כש-pricing מוגדר ואין אף אחד משני הבלוקים, כי שום דבר לא יקרא אותו.
pricing:
  multiplier: 0.85
  overrides:
    - upstream: bedrock-eu
      model: claude-sonnet-4-6
      input: 3.30
      output: 16.50
      cache_read: 0.33
      cache_write: 4.125
שדהנדרשתיאור
multiplierלאברירת מחדל 1. המד מכפיל כל סכום שנמדד בערך הזה, בין אם לפי מחירון ובין אם לפי override, כך ש-0.85 מחייב 85% מהמחיר. חייב להיות גדול מ-0 ולכל היותר 10, וערך מעל 1 הוא markup.
overridesלאשורות של {upstream, model, input, output, cache_read, cache_write} ב-USD למיליון טוקנים. כל ארבעת התעריפים נדרשים. כל אחד חייב להיות גדול מ-0 ולכל היותר 10000.

איך המד מתאים שורת override:

  • שורה מחליפה את מחיר המחירון לבקשות ש-upstream, שהוא upstreams[].name, מגיש עבור model. זה כולל את תעריף fast mode הגבוה יותר, כך שבקשות fast ובקשות standard נמדדות באותם ארבעה תעריפים.
  • מזהה מובנה כגון claude-sonnet-4-6, שמותאם כמו models[].id, מכסה כל צורה מתוארכת, צורה אזורית של Amazon Bedrock, או צורה של Agent Platform של Google Cloud שהמד מתמחר כמודל הזה. כל מחרוזת אחרת, כגון alias או ARN של inference-profile, תואמת את ה-ID שהלקוח שלח או את המחרוזת שנשלחה upstream, בלי תלות ברישיות.
  • כשיש חפיפה בין שורות, המד בוחר את השורה הספציפית ביותר ולא את השורה הראשונה: שורה ש-model שלה הוא מחרוזת המודל המדויקת שנשלחה upstream, אחר כך שורה שתואמת את ה-ID המדויק שהלקוח שלח, ואחר כך שורה שמציינת את המודל המובנה.
  • שם upstream לא מוכר נכשל באתחול, וכך גם שתי שורות ל-upstream אחד שמציינות את אותו מודל, כולל שתי איותים של מודל מובנה אחד. ה-gateway מזהיר באתחול על שורה שאף מודל שאפשר לבקש לא יכול להשתמש בה.
  • בקשות web-search נשארות במחיר המחירון של $0.01. ה-multiplier עדיין חל עליהן.

לתעריפים לפי אזור, תנו לכל אזור upstream עם שם משלו ושורה אחת לכל upstream.

#העלאת מחירים

עם v2.1.271 או חדש יותר בשרת ה-gateway, אפשר להגדיר multiplier מעל 1, עד 10, כדי למדוד יותר ממה שהספק גובה, לדוגמה תעריף chargeback פנימי. הדוגמה הזו מודדת כל בקשה ב-120% מהמחיר:

pricing:
  multiplier: 1.2

עם בלוק admin:, ה-markup חל גם על מגבלות הוצאה. המד סופר 120% מהמחיר, ולכן מפתחים מגיעים לתקרות שלהם מוקדם יותר. ה-gateway רושם אזהרה בזמן האתחול שאומרת זאת.

ה-multiplier לא משנה את מה שספק ה-upstream גובה עבור הבקשות.

אם ה-gateway גם שולח את התעריפים ללקוחות מחוברים, מפתחים צריכים Claude Code v2.1.271 או חדש יותר כדי לראות את ה-markup. לקוחות מוקדמים יותר מתעלמים מ-multiplier מעל 1 ומציגים עלויות בלעדיו.

שרת gateway מוקדם מ-v2.1.271 מסרב להתחיל אם מגדירים multiplier מעל 1.

#שליחת התעריפים ללקוחות מחוברים

עם v2.1.268 או חדש יותר בשרת ה-gateway, ה-gateway גם מכניס את התעריפים מ-pricing למדיניות managed שהוא מגיש, כהגדרת הניהול modelPricing.

מפתחים שמדיניות מתאימה להם רואים אז את תעריפי pricing ב-/usage, בשורת המצב, וב-OpenTelemetry. מפתח שלא תואם לאף מדיניות לא מקבל הגדרות מנוהלות, ולכן המספרים שלו נשארים במחיר המחירון. לקוחות מיישמים את ההגדרה ב-Claude Code v2.1.242 או חדש יותר.

  • מה ה-gateway מוסיף: אלא אם בלוק cli של מדיניות כבר מגדיר modelPricing, ה-gateway מוסיף את ה-multiplier ו, לכל מזהה מודל שלקוח יכול לבקש, את שורת ה-override של ה-upstream הראשון שמגיש את המזהה הזה. תעריף שרק upstream של failover גובה נשאר ב-gateway.
  • Upstreams עם רשימת groups: כשאחד מהם הוא ה-upstream הראשון שמגיש מזהה מודל, ה-gateway לא מוסיף שורה למזהה הזה. מפתחים רואים אז את התעריף של Claude Code עצמו למזהה הזה, שהוא התעריף הסטנדרטי של המודל כש-Claude Code מזהה את המזהה, כפול ה-multiplier.
  • הוצאת מדיניות אחת: הגדירו modelPricing ל-{} בבלוק cli של אותה מדיניות, והמפתחים שלה נשארים במחיר המחירון.
  • שמירה על התעריפים של מדיניות: מדיניות שבלוק cli שלה מגדיר modelPricing עם multiplier או overrides משלה שומרת את ה-modelPricing הזה בשלמותו, וה-gateway לא מוסיף לה תעריפים משלו.

#models

בלוק models הוא רשימת מודלים אופציונלית שאדמין אוצר, מוגשת ב-/v1/models ומשמשת לתרגום מזהי מודל לפי upstream. הוא נדרש לאזורי Amazon Bedrock שאינם בארה"ב, ל-ARN של provisioned-throughput ב-Amazon Bedrock, ולשמות פריסה של Microsoft Foundry.

auto_include_builtin_models: true   # false: expose only the list below
models:
  - id: claude-opus-4-8
    label: Claude Opus 4.8
    # description: optional text shown in clients that surface it
    upstream_model:
      anthropic: claude-opus-4-8
      bedrock: us.anthropic.claude-opus-4-8   # or an inference-profile ARN
      foundry: your-opus-deployment-name

כל מפתח תחת upstream_model חייב להתאים ל-name של upstream מוגדר, שברירת המחדל שלו היא שם הספק. מפתח שלא תואם לאף upstream נכשל באתחול, אז השמיטו את השורות לספקים שאתם לא משתמשים בהם.

#managed

בלוק managed מגדיר מדיניות גישה מבוססת תפקידים לפי קבוצות IdP או דומיין דוא"ל. המדיניות מוערכת לפי הסדר. כברירת מחדל נבחרת ההתאמה הראשונה, ואז היא ממוזגת על בסיס ה-catch-all של match: {}. משתמש שתואם שתי מדיניות תפקיד מקבל רק את הראשונה, ולכן כללי הדחייה של המדיניות השנייה לא חלים אלא אם מיישמים כל מדיניות תואמת. המדיניות מוגשת לכל משתמש ב-GET /managed/settings עם מטמון ETag/304.

managed:
  policies:
    # Specific groups first.
    - match: { groups: [eng-contractors] }
      cli:
        availableModels: [claude-sonnet-4-6]
        permissions: { deny: ["WebFetch", "WebSearch"] }
    # Default catch-all last: matches everyone who authenticated.
    - match: {}
      cli:
        availableModels: [claude-opus-4-8, claude-sonnet-4-6, claude-haiku-4-5]
        # Make the Default option in /model resolve inside each policy's
        # list. The eng-contractors policy inherits enforceAvailableModels.
        enforceAvailableModels: true

match: {} מסוג catch-all, שבדרך כלל מופיע אחרון, נחשב לשכבת בסיס. כל מדיניות אחרת יורשת מה-catch-all כל מפתח שהיא לא מגדירה, ולכן רשומות לפי תפקיד צריכות לפרט רק את מה ששונה מברירת המחדל של הארגון. כללי המיזוג תלויים בסוג המפתח:

  • רשימות היתר: availableModels ו-permissions.allow. הרשימה של מדיניות ספציפית מחליפה במלואה את רשימת הבסיס.
  • רשימות דחייה ומערכי hook: permissions.deny, permissions.ask, disabledMcpjsonServers, deniedMcpServers, blockedMarketplaces, deniedModels, וכל מערך מסוג אירוע ב-hooks. אלה לוקחים את האיחוד של הבסיס והמדיניות, כך שדחייה או hook ביקורת ברמת הארגון לא יכולים להישמט בטעות בגלל דריסה לפי תפקיד.
  • מפתחות מסוג רשומה: env, modelOverrides ו-skillOverrides. אלה עוברים מיזוג שטחי, כך שבלוק env לפי תפקיד דורס מפתחות שהוא מגדיר ויורש את השאר מהבסיס.

availableModels נאכף גם בצד השרת ב-/v1/messages, כך שמודל שנדחה מחזיר 400 בלי קשר למה שהלקוח שולח. רשימה ריקה דוחה כל מודל. הבדיקה מכסה גם את המודל שעליו סשן מתחיל לפני שהמפתח בוחר אחד, ולכן התחילו סשנים על מודל שהמדיניות מתירה.

השער מאמת את ערך model עצמו לפני שהוא מעביר בקשה, כך שערך לא תקין אף פעם לא מגיע ל-upstream. הוא דוחה את הבקשה עם 400 בשני מקרים:

  • כשהערך חסר או ריק, השער דוחה את הבקשה עם ההודעה model is required. הבדיקה הזו דורשת שער שמריץ Claude Code v2.1.228 או חדש יותר.
  • כשהערך קיים אבל אינו מחרוזת, השער דוחה את הבקשה עם ההודעה model must be a string. נדרש שער שמריץ Claude Code v2.1.221 או חדש יותר.
MatcherBehavior
match: {}תואם כל משתמש מאומת. התחילו באחד כזה והוסיפו מדיניות בהיקף קבוצה מעליו אחר כך.
match: { groups: [a, b] }תואם אם ה-claim groups ב-JWT מכיל אחת מהקבוצות שברשימה. תלוי רישיות: הקבוצות חייבות להתאים בדיוק לרישיות של ה-IdP.
match: { email_domain: example.com }תואם את החלק שאחרי ה-@ האחרון ב-claim email של ה-JWT, בלי תלות ברישיות. מקבל דומיין אחד לכל מדיניות.
match: { groups: [a], email_domain: example.com }שני התנאים חייבים להתאים

משתמש מאומת שלא תואם אף מדיניות מקבל את ברירות המחדל של השער, כלומר כל מודל בקטלוג ובלי הגדרות managed. הוסיפו catch-all של match: {} בסוף אם רוצים מדיניות ברירת מחדל מובטחת.

שימו כללי דחייה ברמת הארגון במדיניות match: {}, כי כללי מדיניות קבוצה חלים רק כל עוד הטוקן של המשתמש נושא את הקבוצה הזו.

[!NOTE]

השער לא מחזיק ספריית משתמשים משלו. הוא מאשר כל בקשה לפי טוקן ה-IdP של המשתמש, קורא חברות בקבוצות מ-claim groups של הטוקן ומעריך מדיניות מולו. אין רשימה למנות ואין חשבונות ליצור מראש, ולכן אין נקודת קצה של SCIM, כי אין ל-SCIM לאן לסנכרן.

נהלו את מחזור החיים של משתמשים וקבוצות במקור האמת, שהוא הקצאת SCIM המקורית של ה-IdP או פלטפורמת identity-governance ייעודית. חברות בקבוצות וביטול הקצאה שמנוהלים שם זורמים לשער אוטומטית דרך הטוקן. אם רוצים הקצאת SCIM של חשבונות Claude עצמם, זו יכולת של Claude for Enterprise.

חלים שני לוחות זמנים של הפצה:

  • תוכן המדיניות: עריכת מדיניות ופריסה מחדש מגיעות ללקוחות Claude Code מחוברים בסקר הבא של managed-settings, בתוך שעה, מלבד השינויים שחלים רק בהפעלה הבאה
  • חברות בקבוצה: שינוי חברות המשתמש בקבוצה משנה איזו מדיניות תואמת אותו. זה נכנס לתוקף בהנפקה מחדש הבאה של הסשן, כלומר הרענון השקט הבא, בגבול של session.ttl_hours.

Claude Desktop פועל לפי לוח הזמנים שלו.

#יישום כל מדיניות תואמת

משתמש שתואם כמה מדיניות תפקיד מקבל רק את הראשונה אלא אם מגדירים policy_mode: layered ליד policies. עם layered, כל מדיניות שתואמת את המשתמש חלה, עד למדיניות match: {} הראשונה.

policy_mode דורש Claude Code v2.1.316 או חדש יותר בשרת השער. שער בגרסה שאין בה את זה מסרב להתחיל כשהוא מוצא את המפתח. שדרגו כל replica לפני שמוסיפים את המפתח, והסירו את המפתח לפני חזרה לגרסה מוקדמת יותר. בדוגמה הזו יש קבוצה אחת שמאבדת את WebFetch ואחת שמקבלת את Opus:

managed:
  policy_mode: layered
  policies:
    - match: { groups: [no-web] }
      cli:
        permissions: { deny: ["WebFetch"] }
    - match: { groups: [opus-users] }
      cli:
        availableModels: [opus, sonnet]
    - match: {}
      cli:
        availableModels: [sonnet]
        enforceAvailableModels: true

הטבלה מראה מה מקבל משתמש שנמצא גם ב-no-web וגם ב-opus-users תחת ברירת המחדל, first_match, ותחת layered.

Settingfirst_matchlayered
availableModelssonnetopus, sonnet
enforceAvailableModelstruetrue
permissions.denyWebFetchWebFetch

השער ממזג כל מדיניות תואמת על אלה שרשומות מתחתיה, לפי אותם כללי מיזוג כמו שכבת הבסיס:

  • רשימות היתר, ערכים בודדים, ובלוקים כמו sandbox: כל אחד מגיע בשלמותו מהמדיניות התואמת הראשונה ברשימה שמגדירה אותו, כך שרשימות availableModels של שתי קבוצות לא מצטברות.
  • רשימות דחייה ומערכי hook: אלה מצטברים על פני כל מדיניות תואמת, כך שמשתמש בשתי קבוצות מקבל את כללי הדחייה של שתי הקבוצות.
  • env, modelOverrides ו-skillOverrides: הרשומות מתמזגות לפי שם, והמדיניות התואמת הראשונה ברשימה שמגדירה שם מספקת את הערך שלו.
  • מפתחות desktop: אלה מתמזגים לפי הכללים לבלוק desktop הבסיסי.

[!WARNING]

מדיניות יכולה להצטבר לכללים רופפים יותר ממה שכל אחת מהן נותנת לבדה. לדוגמה, מדיניות match: {} מגדירה sandbox.enabled: true, מדיניות של קבוצה אחת מגדירה permissions.allow: ["Bash"], ומדיניות של קבוצה אחרת מגדירה sandbox.enabled: false. משתמש בשתי הקבוצות מקבל Bash מותר עם sandbox כבוי. במקרה הזה, רשמו קודם את המדיניות שמתירה את Bash, והעתיקו לתוכה את כל בלוק sandbox של מדיניות match: {}.

עם layered, השער מסרב להתחיל על חלק מההגדרות, כולל אלה:

  • תבנית !: שלילת ! בכלל Read או Edit ברשימת permissions.deny או permissions.ask של כל מדיניות, כולל מדיניות match: {}
  • מגבלה על hooks מחוץ ל-catch-all: disableAllHooks, allowedHttpHookUrls, או httpHookAllowedEnvVars בכל מדיניות שאינה match: {}

#התחלת סשנים על מודל שהמדיניות מתירה

אם availableModels משמיט את מודל ברירת המחדל של Claude Code, סשנים מקבלים תשובות 400 עד שהמפתח בוחר מודל מהרשימה, לדוגמה עם /model. בסשנים של השער ברירת המחדל היא מודל Opus שאליו הכינוי opus מצביע, ו-availableModels לבדו לא משנה אותה.

כדי לתקן את זה, הגדירו enforceAvailableModels: true באותו בלוק cli, ואז בדקו איזה סוג רשומה יש ברשימה:

  • כינוי כמו sonnet, או מזהה מובנה כמו claude-sonnet-4-6: סשנים מתחילים על אחד מהמודלים האלה, ואפשרות Default ב-/model מצביעה אליו
  • אין כינוי או מזהה מובנה ברשימה: סשנים יכולים להמשיך להתחיל על ברירת המחדל המובנית, ולכן הגדירו גם model לאחד מהמזהים שברשימה בבלוק cli של אותה מדיניות

המדיניות הזו מפרטת מזהה מותאם אחד ש-models מגדיר, ומתחילה סשנים על המזהה הזה:

managed:
  policies:
    - match: { groups: [restricted-projects] }
      cli:
        availableModels: [restricted-claude-opus-4-8]
        enforceAvailableModels: true
        model: restricted-claude-opus-4-8
        env:
          ANTHROPIC_DEFAULT_OPUS_MODEL: restricted-claude-opus-4-8   # opus and Default resolve to the ID too

#ערכי matcher שעוצרים את השער בעלייה

בעלייה, השער בודק את בלוק match של כל מדיניות ואת רשימת admin_groups. כל אחד מהערכים האלה עוצר את השער עם שגיאה שמציינת את השדה:

  • רשימת groups ריקה
  • רשומה ריקה ב-groups או ב-admin_groups
  • email_domain ריק
  • email_domain שמכיל @, רווח לבן, או פסיק. השער חותך רווחים מהערך ומסיר @ מוביל אחד לפני הבדיקה הזו. כתבו דומיין חשוף אחד, כמו example.com.

לפני v2.1.232, השער עלה עם הערכים האלה. לכל ערך הייתה ההשפעה הזו:

  • email_domain ריק: השער דילג על בדיקת הדומיין, כך שמדיניות עם email_domain ריק ובלי רשימת groups תאמה כל משתמש מאומת
  • רשימת groups ריקה: המדיניות לא תאמה אף אחד
  • email_domain שמכיל @, רווח לבן, או פסיק: המדיניות לא תאמה אף אחד
  • רשומה ריקה ב-groups או ב-admin_groups: הרשומה תאמה משתמש רק כש-claim groups של ה-IdP של המשתמש הכיל גם רשומה ריקה. ב-admin_groups, ההתאמה הזו העניקה גישת מנהל. אם רשימת admin_groups שלכם מעולם לא הכילה רשומה ריקה, אף אחד לא קיבל גישת מנהל בדרך הזו.

#בחירה בין cli ל-code

[!WARNING]

כשמדיניות משתמשת במפתח code, כל אחד מאלה עוצר את השער מלהתחיל:

  • גרסת השער: code דורש Claude Code v2.1.296 או חדש יותר בשרת השער. שער מוקדם יותר מסרב להתחיל כשהוא מוצא את המפתח. שדרגו כל replica לפני שמוסיפים את המפתח, ושנו את code בחזרה ל-cli לפני חזרה לגרסה מוקדמת יותר.
  • מפתחות מעורבים: קובץ שיש בו גם code וגם cli, או האיות המוקדם יותר settings, עוצר את השער בעלייה. שימו כל בלוק תחת מפתח אחד, בעריכה אחת.

הגדרות Claude Code של מדיניות, כמו כלל שדוחה קריאת קבצי .env, נכנסות לבלוק תחת המפתח cli או code. code הוא המפתח המומלץ, ו-cli הוא המפתח הישן. שני המפתחות מקבלים אותו תוכן. המפתח קובע איפה ההגדרות נאכפות:

  • cli: הטרמינל, התוספים של VS Code ו-JetBrains, ו-Agent SDK. תחת cli, לשונית Code של Claude Desktop מקבלת את ההגדרות הנגזרות, כך שכלל בהיקף כמו Read(./.env) לא עוצר משתמש שם.
  • code: אותם מקומות, וגם לשונית Code של Claude Desktop יכולה להיות מכוסה.

קובץ שמשתמש ב-cli עובד כפי שעבד, ושער שמוצא cli במדיניות עם מפתח desktop מזהיר בעלייה ועולה בכל זאת. עברו ל-code כדי שההגדרות יוכלו לכסות גם את לשונית Code.

לפני המעבר, קראו את החלת הגדרות code בלשונית Code. המדיניות צריכה מפתח desktop והמחשבים של המשתמשים צריכים הגדרה לפני שההגדרות חלות שם, וחיפוש באינטרנט נכבה ב-Claude Desktop.

המדיניות הזו שמה את כלל הדחייה תחת code, עם מפתח desktop ריק:

managed:
  policies:
    - match: {}
      code:
        permissions: { deny: ["Read(./.env)"] }
      desktop: {}

במעבר, מחקו כל שורת serve_to_desktop באותה עריכה שמשנה את שמות הבלוקים. איפה שהוראה מציינת את בלוק cli, השתמשו בבלוק code שלכם.

serve_to_desktop: true היא דרך ישנה להציע את הגדרות cli של מדיניות ללשונית Code. אין לה השפעה כש-Claude Desktop מתחבר דרך bootstrapUrl. כל עוד המדיניות שלכם משתמשת ב-cli, אזהרת עלייה שמציינת את המפתח הזה אומרת שההגדרות האלה לא מגיעות ללשונית Code:

  • כדי לכסות את לשונית Code: עברו ל-code, אחרי שהמחשבים של המשתמשים עומדים בתנאים ב-החלת הגדרות code בלשונית Code
  • כדי להישאר על cli: הגדירו serve_to_desktop: false ליד cli במדיניות כדי להשתיק את האזהרה

#מה נכנס ב-cli

כל ערך code או cli הוא מסמך managed-settings.json מלא של Claude Code, אותה סכמה שהיית פורס דרך MDM או /etc/claude-code/managed-settings.json, מבוטאת כאן כ-YAML. ה-CLI מחיל את המסמך שנמסר בשכבה המנוהלת, מעל הגדרות משתמש ופרויקט, במקום הגדרות שמנוהלות בשרת. לכן הוא מתעלם מההגדרות המוגבלות למקורות מדיניות ברמת מערכת ההפעלה, כגון policyHelper ו-wslInheritsWindowsSettings.

השער מאמת כל מסמך מול סכמת ההגדרות של ה-CLI בעת האתחול, כך שמפתח ברמה העליונה שאינו מזוהה גורם לכשל באתחול עם שגיאה שמציינת כל מפתח פוגע. חלקים שנפתחו בכוונה בסכמה עדיין מקבלים ערכים שרירותיים, כי לקוחות חדשים יותר עשויים לזהות רשומות שהסכמה של השער אינה מזהה. המפתחות הפתוחים האלה כוללים את env, pluginConfigs, ומפתחות מקוננים תחת permissions.

מכיוון שהאימות משתמש בסכמה הארוזה עם הגרסה המותקנת של השער, הכנסת מפתח הגדרות ברמה העליונה שהוצג במהדורת Claude Code חדשה יותר לתצורה מנוהלת דורשת שדרוג של השער תחילה. בצע בדיקת עשן למדיניות חדשה על לקוח אחד לפני ההפצה.

הפניה המלאה למפתחות נמצאת בהגדרות Claude Code. המפתחות שרוב המפעילים ניגשים אליהם תחילה:

managed:
  policies:
    - match: {}
      cli:
        # Model access (also enforced server-side at /v1/messages)
        availableModels: [claude-opus-4-8, claude-sonnet-4-6, claude-haiku-4-5]
        enforceAvailableModels: true              # Default resolves inside the list

        # Permission policy
        permissions:
          deny:
            - "WebFetch"
            - "Read(./.env)"
            - "Read(./secrets/**)"
          disableBypassPermissionsMode: disable   # blocks --dangerously-skip-permissions
        allowManagedPermissionRulesOnly: true     # ignore user/project permission rules

        # Environment pushed into the CLI process. DISABLE_UPDATES blocks
        # background and manual updates; DISABLE_AUTOUPDATER stops only
        # background updates.
        env:
          DISABLE_UPDATES: "1"                    # pin versions via your own distribution

        # Org-wide hooks. Hook commands run on developer machines, not the
        # gateway, so the path must exist on every client OS in the policy.
        hooks:
          PostToolUse:
            - matcher: "Edit|Write"
              hooks:
                - { type: command, command: /usr/local/bin/audit-edit.sh }
מפתחנאכף על ידיהשפעה
availableModelsשער + CLIרשימת מודלים מותרים. נבדק גם ב-/v1/messages, כך שלקוח שעבר שינוי לא יכול לעקוף את זה.
deniedModels, availableModelsMatchשער + CLIחסימת מודלים או גרסאות מסוימים ש-availableModels היה מתיר אחרת. מודל חסום נדחה עם 400 ב-/v1/messages ומושמט מ-/v1/models. הבדיקה של השער עצמו דורשת Claude Code v2.1.299 או מאוחר יותר בשרת השער. הבדיקה של ה-CLI דורשת v2.1.283 או מאוחר יותר בלקוחות, ולקוחות מוקדמים יותר מתעלמים משני המפתחות.
permissions.allow / .denyCLIכללי כלים ופקודות. ראה הרשאות ומה כלל Bash אינו תואם.
permissions.disableBypassPermissionsModeCLIהגדר ל-disable כדי לחסום את bypassPermissions, המצב שמדלג על בקשות הרשאה, ואת הדגל --dangerously-skip-permissions
allowManagedPermissionRulesOnlyCLIכאשר true, הגדרות מנוהלות הופכות למקור ההגדרות היחיד של כללי הרשאה. הרשומה allowManagedPermissionRulesOnly מפרטת כל מקור ש-Claude Code מתעלם ממנו אז.
envCLIמשתני סביבה שמוזגים לתהליך ה-CLI. השתמש לטלמטריה, עדכון אוטומטי ודריסות של שמות מודלים.
hooksCLIhooks ברחבי הארגון
managedMcpServersCLIשרתי MCP מרוחקים שמסופקים לכל מפתח תואם לצד השרתים שהם מוסיפים בעצמם, http ו-sse בלבד. ראה שרתי MCP במדיניות. דורש Claude Code v2.1.259 או מאוחר יותר בשרת השער ובלקוחות. לקוחות מוקדמים יותר מתעלמים מהמפתח.

מכיוון שההגדרות האלה מגיעות דרך הרשת, ה-CLI מציג לכל מפתח תיבת דו-שיח לאישור אבטחה לפני החלת ההגדרות המפורטות להלן:

  • hooks
  • משתני env שדורשים את אישור המפתח, כגון משתני proxy ו-base-URL
  • הגדרות הרצת מעטפת כגון apiKeyHelper ו-statusLine
  • הגדרות הבינארי של ארגז החול sandbox.bwrapPath, sandbox.socatPath ו-sandbox.ripgrep
  • הגדרות ארגז חול שמיירטות תעבורה, מזריקות אישורים או מחלישות בידוד, כגון sandbox.network.tlsTerminate והגדרות פורט ה-proxy. תיבות דו-שיח לאישור אבטחה מפרטות את כולן.

זיכרון אישור מכסה כמה זמן אישור נשמר ומתי תיבת הדו-שיח מופיעה שוב.

Claude Code מחיל חלק ממשתני env שנמסרו בלי להציג למפתח את תיבת הדו-שיח לאישור, כגון הגדרות בחירת מודל ומגבלות מספריות. משתנים שנמסרו אחרים יכולים לדרוש את אישור המפתח. ערך proxy, base-URL או OTEL_EXPORTER_OTLP_ENDPOINT שאינו ריק תמיד דורש זאת. כאשר משתנה שנמסר זקוק לאישור, תיבת הדו-שיח מציינת אותו. משתני סביבה ותיבת הדו-שיח לאישור כולל את הפרטים, כולל ארבעה מתגי פרטיות שהערך שנמסר שלהם קובע אם הם זקוקים לאישור.

תצורת הטלמטריה של השער דוחפת את OTEL_EXPORTER_OTLP_ENDPOINT, כך שהגדרת telemetry.forward_to מפעילה את תיבת הדו-שיח בכל לקוח אינטראקטיבי. תיבת הדו-שיח מגינה על המחשב של המפתח מפני שער שנפגע או עוין, ולא על הארגון מפני המפתח.

הרצה לא אינטראקטיבית, כגון claude -p, סשן Agent SDK, או סשן בלשונית Code של Claude Desktop, לא יכולה להציג את תיבת הדו-שיח. היא מחילה את ההגדרות שנדחפו להרצה הזו בלבד ואינה רושמת אותן כמאושרות, כך שהסשן האינטראקטיבי הבא של המפתח עדיין מציג את תיבת הדו-שיח.

אם מפתח מסרב, Claude Code יוצא מהסשן הזה במקום להחיל את המדיניות. כאשר אתה דוחף hook חדש, או כל משתנה env שמפעיל את תיבת הדו-שיח, למדיניות רחבה, כל מפתח תואם רואה לכן את תיבת הדו-שיח בסשנים האינטראקטיביים שלו. סשן אינטראקטיבי שרץ מציג אותה בסקר השעתי הבא, ואחרת היא מופיעה בהפעלה האינטראקטיבית הבאה של המפתח.

המפתח cli נקרא settings במהדורות מוקדמות יותר, והשער עדיין מקבל את האיות הזה ככינוי. לפריסות חדשות, השתמש ב-code.

#בדיקת מדיניות לפני פריסה

כדי לבדוק שינוי מדיניות, הפעל את השער מול מסד נתונים Postgres חד-פעמי. השער מתחבר ל-Postgres ומחיל את מיגרציות הסכמה שלו לפני שהוא בודק את התוכן של בלוקי cli, code ו-desktop. כאשר הוא לא יכול להגיע למסד הנתונים, ההפעלה נעצרת ב-could not connect to Postgres ואינה מדווחת דבר על התוכן שלהם.

#חלון הקשר בסשנים בטרמינל

סשנים בטרמינל שמחוברים דרך /login משתמשים בחלון הקשר של 1M עבור Opus 4.7 ומאוחר יותר, Sonnet 5 ומאוחר יותר, ומודלי Fable. מזהה המודל אינו זקוק לסיומת [1m], והסשנים נדחסים בערך ב-967K טוקנים. לפני Claude Code v2.1.287 במחשב של המפתח, Claude Code התייחס למודלי Opus ו-Fable כבעלי חלון של 200K אלא אם מזהה המודל הסתיים ב-[1m].

כדי שסשנים בטרמינל יידחסו בגבול 200K, הגדר את חלון הדחיסה האוטומטית ב-env של המדיניות:

managed:
  policies:
    - match: {}
      cli:
        env:
          CLAUDE_CODE_AUTO_COMPACT_WINDOW: "200000"

Claude Code מחיל את המשתנה הזה בלי להציג למפתח את תיבת הדו-שיח לאישור. המשתנה חל על כל מודל, כולל מזהי מודל שמסתיימים ב-[1m].

כדי לכבות הקשר של 1M, הגדר CLAUDE_CODE_DISABLE_1M_CONTEXT: "1" באותו בלוק env. Claude Code מתייחס אז לכל מודל כבעל חלון של 200K. בסשנים אינטראקטיביים, כל מפתח מאשר את המשתנה הזה בתיבת הדו-שיח לאישור לפני שהוא נכנס לתוקף.

#מטמון פרומפט של שעה

כדי לבקש את TTL של מטמון הפרומפט של שעה במקום ברירת המחדל של חמש דקות, הוסף את המפתחות האלה לבלוק code, cli או settings קיים של מדיניות והפעל מחדש את השער. המפתחות זקוקים ל-Claude Code v2.1.242 או מאוחר יותר בשרת השער ובלקוחות.

promptCacheTtl מכסה את השיחה הראשית. subagentPromptCacheTtl הוא אופציונלי ומכסה סוכני משנה, תהליכי עבודה ובקשות ברקע. הדוגמה הזו מוסיפה את שניהם למדיניות match: {} עם מפתח cli:

managed:
  policies:
    - match: {}
      cli:
        promptCacheTtl: 1h
        subagentPromptCacheTtl: 1h

[!WARNING]

הגדר את המפתחות רק אם ה-upstreams שלך מציעים את ה-TTL של שעה לכל מודל שהשער משרת. אם upstream דוחה את ה-TTL, הבקשה נכשלת, והשער וגם Claude Code אינם מנסים אותה שוב עם TTL של חמש דקות. עבור Amazon Bedrock, בדוק מודלים, אזורים ומגבלות נתמכים.

כדי לאשר את promptCacheTtl, התחבר לשער כמשתמש שהמדיניות תואמת לו ובדוק באיזה TTL כתיבות המטמון שלך השתמשו. העבר --model כדי לחזור על הבדיקה לכל מודל שהשער משרת.

כתיבות מטמון של שעה עולות יותר מכתיבות של חמש דקות. כדי שמגבלות הוצאה יחשבו את התעריף הגבוה יותר, אתה זקוק ל-v2.1.286 או מאוחר יותר בשרת השער.

#שרתי MCP במדיניות

כדי לספק שרתי MCP ללקוחות Claude Code שמדיניות תואמת, הגדר managedMcpServers בבלוק cli של המדיניות הזו. אתה זקוק ל-Claude Code v2.1.259 או מאוחר יותר בשרת השער ובלקוחות.

השער בודק כל רשומה בעת האתחול עם אותם כללים ש-Claude Code מחיל בלקוח, ואם רשומה נכשלת בבדיקה, השער מסרב להתחיל ומציין את הרשומה.

אם אתה כותב הפניה ${VAR} ב-gateway.yaml, השער פותר אותה מהסביבה שלו בעת האתחול דרך הרחבת סודות לפני שהוא מריץ את בדיקות הרשומה, כך שכל לקוח תואם מקבל את הערך המילולי ויכול לקרוא אותו. הנחיית הכותרות לשרתים שמסופקים חלה על הערך המורחב.

השער דוחה את האיות mcpServers של .mcp.json בבלוק cli, ושגיאת האתחול שלו מציינת את managedMcpServers כמפתח לשימוש. לפני v2.1.259, השער דחה כל הגדרת שרת MCP בבלוק cli.

#שכבת Claude Desktop

אם הארגון שלכם גם פורס את Claude Desktop, אותו שער משרת את שני הלקוחות. כוונו את bootstrapUrl, בההגדרות המנוהלות של Claude Desktop, אל <listen.public_url>/user/bootstrap. Claude Desktop גוזר את מנפיק ה-OAuth מהכתובת הזו, מריץ את אותה התחברות ב-device-code מול השער הזה, ושולף את ההגדרות שלו מהתשובה.

[!NOTE]

דורש Claude Code בגרסה v2.1.203 ואילך בשרת השער, והצטרפות מפורשת: /user/bootstrap מחזיר 404 אלא אם המדיניות שתואמת למשתמש נושאת מפתח desktop. desktop: {} ריק מצטרף מדיניות, ומפתח desktop בשכבת הבסיס match: {} מצטרף כל מדיניות שיורשת אותה. יומן הביקורת רושם כל בקשה כ-desktop_bootstrap.serve או desktop_bootstrap.denied.

אם אינכם פורסים את Claude Desktop, השאירו את desktop מחוץ למדיניות שלכם לגמרי. השער אז מחזיר 404 מ-/user/bootstrap לכל משתמש.

#הגדרות שהשער גוזר עבור Claude Desktop

השער גוזר חלק גדול מתשובת ה-bootstrap מבלוק cli או code של המדיניות התואמת ומהגדרות השער ברמה העליונה:

  • רשימת המודלים, מ-availableModels. הרשימה משמיטה מודלים שהמדיניות חוסמת באמצעות deniedModels או availableModelsMatch: exact. המסנן הזה דורש Claude Code בגרסה v2.1.299 ואילך בשרת השער. הקשר מורחב ב-Claude Desktop מכסה את אפשרות ההקשר של 1M לכל מודל

  • כלים מושבתים, מרשומות permissions.deny עם שם כלי חשוף. אם תגדירו disabledBuiltinTools בבלוק desktop של המדיניות, השער מגיש את האיחוד של הערך שלכם והרשימה הנגזרת, כך שאפשר להשבית כלים נוספים בדרך הזו אבל אי אפשר להפעיל מחדש כלי שהשבתתם דרך permissions.deny

  • רשימת ההיתר ליציאה, מ-sandbox.network.allowedDomains. אם תגדירו coworkEgressAllowedHosts בבלוק desktop של המדיניות, השער משתמש בערך הזה במקום הרשימה הנגזרת. אם רשימת ההיתר שהשער מגיש כוללת * והשער גם לא מגיש את allowedWorkspaceFolders של Claude Desktop, Claude Desktop לא מפעיל את ארגז החול של Bash בלשונית Code

  • נקודת קצה OTLP שמצביעה על השער עצמו, ותכונות הזהות של המשתמש המחובר. השער מעביר את הייצואים שהוא מקבל בנקודת הקצה הזו ליעדי forward_to שלכם. הוא כולל את נקודת הקצה ואת התכונות כשמגדירים גם את telemetry.forward_to וגם את listen.public_url.

    Claude Desktop מייצא כל אות בקידוד אחד: http/protobuf, או http/json כשמגדירים את OTEL_EXPORTER_OTLP_PROTOCOL או אחת מהווריאנטים לפי אות שלו ל-http/json ב-env של המדיניות. לפני Claude Code v2.1.261 בשרת השער, התשובה הגדירה http/json בכל מקרה, ולכן אספן שמקבל רק protobuf דחה את הייצואים של Claude Desktop

כדי להגדיר את disabledBuiltinTools, את coworkEgressAllowedHosts, או את ההגדרה managedMcpServers של Claude Desktop עצמו בבלוק desktop של מדיניות, צריך Claude Code בגרסה v2.1.232 ואילך בשרת השער. managedMcpServers של Claude Desktop מקבל ערך מערך ולא אובייקט.

השער משמיט מתשובת ה-bootstrap מפתחות שאין להם מקבילה ב-Claude Desktop, כמו hooks וכללי הרשאה תחומים כמו Bash(npm *).

#החלת הגדרות code בלשונית Code

הגדרות Claude Code שמדיניות מחזיקה תחת המפתח code שלה חלות בלשונית Code של Claude Desktop כשכל אלה מתקיימים:

  • למדיניות יש גם מפתח desktop, ו-desktop: {} ריק נחשב
  • Claude Desktop בגרסה 2.9939.2 ואילך
  • הגדרות Claude Code המנוהלות במכונה מציינות את השער הזה
  • המכונה הזו מגיעה לשער דרך HTTPS ברשת פרטית

שני התנאים האחרונים חלים על המכונה שמריצה את Claude Code עבור ההפעלה. בהפעלה מקומית, זו המחשב של המשתמש עצמו. בהפעלת לשונית Code דרך SSH, זה המארח המרוחק.

פרסו את ההגדרות המנוהלות בצד הלקוח למכונות האלה לפני שמשנים את השם מ-cli ל-code. כששני התנאים הראשונים מתקיימים ואחד משני האחרונים נכשל, משתמש שהמדיניות תואמת לו מקבל אחת מהתוצאות האלה:

  • דרך HTTPS, כש-Claude Desktop כולל את Claude Code v2.1.296 ואילך: לשונית Code לא מופעלת, והתשובה להנחיה של המשתמש אומרת למה
  • דרך HTTPS, כש-Claude Desktop כולל גרסה מוקדמת יותר: לשונית Code מופעלת בלי הגדרות code שלכם, ושום דבר בהפעלה לא אומר זאת
  • דרך HTTP רגיל: לשונית Code מופעלת בלי הגדרות code שלכם, בכל גרסה ש-Claude Desktop כולל

כשפרוקסי מול השער עונה ל-/managed/settings ב-404 משלו, לשונית Code גם מופעלת בלי הגדרות code שלכם, כולל במכונה שעומדת בכל ארבעת התנאים.

במדיניות שיש בה מפתח desktop, בלוק code שמחזיק הגדרות מכבה את כלי WebSearch ב-Cowork, ב-Chat ובלשונית Code. לשרתי MCP, ראו איפה managedMcpServers חל.

#הגדרת הגדרות Claude Desktop ישירות

הוסיפו את בלוק desktop האופציונלי לצד cli כדי להגדיר הגדרות Claude Desktop ישירות. כתבו הגדרות ממדריך ההגדרות המנוהלות של Claude Desktop כשמות מפתח שטוחים. השמיטו מפתחות ש-Claude Desktop קורא רק מ-MDM או מקבצים מקומיים, כמו bootstrapUrl. השער דוחה אותם בעלייה.

הדוגמה הזו מגדירה שלושה מפתחות Claude Desktop לקבוצה eng-contractors לצד הגדרות cli שלה:

managed:
  policies:
    - match: { groups: [eng-contractors] }
      cli:
        availableModels: [claude-sonnet-4-6]
        enforceAvailableModels: true
      desktop:
        isLocalDevMcpEnabled: false
        disableAutoUpdates: true
        banner: { text: "Contractor build: internal use only" }

כל מפתח הוא אופציונלי. Claude Desktop מחיל את ברירת המחדל שלו לכל מפתח שמשמיטים.

#מה השער דוחה בעלייה

השער מאמת כל בלוק desktop בעלייה מול סכמת ההגדרות ש-Claude Desktop עצמו משתמש בה, כך שטעות עולה בהפעלת השער כשגיאה שמציינת את המפתח ולא מגיעה לכל שולחן עבודה מחובר. השער נכשל בעלייה כשבלוק מכיל:

  • מפתח לא מוכר
  • מפתח מוכר שהערך שלו Claude Desktop היה דוחה או משמיט בשקט, כמו ערך ריק או תת-מפתח עם שגיאת כתיב בתוך רשומה מקוננת. לפני v2.1.260, השער השמיט בשקט שדה עם שגיאת כתיב בתוך אובייקט מקונן של רשומת managedMcpServers או orgPluginSettings במקום להיכשל בעלייה.
  • מפתח שהשער מחשב בעצמו: חיבור ההסקה, רשימת המודלים, וממסר ה-OTLP. הגדירו אותם דרך upstreams, models, ו-forward_to של מקטע telemetry.
  • כינוי ישן של מפתח נוכחי. בשגיאת העלייה, השער מציין את המפתח הקנוני לכתיבה.

אם משתמשים בערך או בצורת רשומה שהוצאו משימוש, כמו רשומת managedMcpServers בלי transport, השער עולה ורושם אזהרה שמציינת את התחליף.

לפני v2.1.232, השער קיבל רשימה קבועה של 11 מפתחות feature-gate, כמו chatTabEnabled ו-disableAutoUpdates, ודחה כל מפתח אחר בעלייה. לפני v2.1.227, השער גם דחה את chatTabEnabled ואת chatAdvancedFileAnalysisEnabled בעלייה.

#מפתחות שדורשים גרסת שער או Claude Desktop מאוחרת יותר

השער מאמת בלוק desktop מול הסכמה שמצורפת לגרסה המותקנת שלו, כמו שהוא עושה לבלוק cli. כדי לספק הגדרה שהוצגה במהדורת Claude Desktop חדשה יותר, שדרגו קודם את השער. לדוגמה, userPluginMarketplacesEnabled ו-userPluginUploadsEnabled דורשים Claude Code בגרסה v2.1.260 ואילך בשרת השער ו-Claude Desktop 1.37937.0 ואילך במכונות של החברים.

blockReadsOutsideWorkingDirectories, disableBypassPermissionsMode, configRecheckIntervalMinutes ו-sshClientPath דורשים Claude Code בגרסה v2.1.281 ואילך בשרת השער. כך גם הערך required של microsoftAuthBroker והשדה continuousAccessEvaluation של רשומת managedMcpServers של Microsoft 365. מהדורות Claude Desktop שקדמו לערך required קוראות אותו כ-disabled, לכן הגדירו required רק אחרי ש-Claude Desktop של כל חבר תומך בו. מדריך ההגדרות המנוהלות של Claude Desktop מציין את המהדורה שקוראת כל מפתח לראשונה.

[!NOTE]

sshTransport דורש Claude Code בגרסה v2.1.293 ואילך בשרת השער.

אם מגדירים orgPluginSettings בבלוק desktop של מדיניות, השער מגיש אותו בצורת המערך ש-Claude Desktop 1.15200.0 ואילך קורא. שולחנות עבודה ישנים יותר מתעלמים מהמערך ולא אוכפים מדיניות כלי תוסף, לכן עדכנו חברים ל-1.15200.0 ואילך לפני שמסתמכים על זה.

#איך מדיניות תפקיד יורשת את בלוק desktop הבסיסי

השער ממלא מפתחות שבלוק desktop של מדיניות לא מגדיר מבלוק desktop של ה-catch-all match: {}, באותה דרך שהוא ממלא בלוק cli של מדיניות מהבסיס. אם מגדירים disabledBuiltinTools או builtinToolPolicy גם בבסיס וגם במדיניות תפקיד, השער שומר את ההגבלה של הבסיס:

  • disabledBuiltinTools: השער משתמש באיחוד של רשימת הבסיס ורשימת המדיניות
  • builtinToolPolicy: אם מגדירים כלי לערך שאינו allow בבסיס, השער שומר את הערך הזה גם אם מגדירים allow לאותו כלי במדיניות תפקיד

לכל מפתח אחר, אם מגדירים אותו במדיניות התפקיד, השער משתמש בערך של מדיניות התפקיד. השער מחליף מערך או אובייקט מקונן כמו banner בשלמותו, כך שאם מגדירים banner.text במדיניות תפקיד, השער משמיט את banner.backgroundColor של הבסיס.

#מתי שינוי מדיניות מגיע ל-Claude Desktop

אחרי שפורסים מחדש את השער עם מדיניות ששונתה, Claude Desktop מחיל את רוב ההגדרות רק כשהוא מופעל בפעם הבאה:

  • סגור: Claude Desktop שולף את תשובת ה-bootstrap כשהוא מופעל, כך שהשינוי חל מההפעלה הבאה
  • פתוח: Claude Desktop בודק תשובה ששונתה כל 10 דקות כברירת מחדל ומחיל כמה הגדרות בלי הפעלה מחדש. לשאר, כמו skillCreationEnabled, המשתמש רואה כרטיס Relaunch Claude Desktop בסרגל הצד ושומר את ההגדרות הקודמות עד שהוא מפעיל מחדש את האפליקציה. אחרי 24 שעות כברירת מחדל, Claude Desktop מציג תיבת דו-שיח להפעלה מחדש ומפעיל את עצמו מחדש אחרי 2 דקות של חוסר פעילות

כדי לקצר את 24 השעות, הגדירו relaunchEnforcementHours בבלוק desktop של המדיניות. צריך Claude Code בגרסה v2.1.260 ואילך בשרת השער ו-Claude Desktop 1.40609.0 ואילך במכונות של החברים. עם 0, תיבת הדו-שיח מופיעה ברגע ש-Claude Desktop מוצא את השינוי.

#הקשר מורחב ב-Claude Desktop

אם מגישים את Claude Desktop מהשער, בורר המודלים שלו מציע אפשרות הקשר של 1M לכל מודל ברשימה שיכול לרוץ עם חלון הקשר של 1M. אלה כוללים את Claude Opus 4.6 ואילך, Claude Sonnet 4.6 ואילך, ואת מודלי Fable. האפשרות היא וריאנט [1m] של המודל, שהקשר מורחב מתאר. צריך Claude Code בגרסה v2.1.284 ואילך בשרת השער.

רשומת models לא מקבלת אפשרות 1M כש:

  • upstream שיכול להגיש את הרשומה ממפה אותה למודל בלי תמיכה ב-1M, כולל upstream שהשער מגיע אליו רק ב-failover
  • לא ה-id שלה ולא אף אחד מערכי upstream_model שלה מציין מודל Claude, כמו כינוי מותאם שמנותב ל-ARN של פרופיל הסקה של אפליקציה

כדי לשנות מה הבורר מציע, השתמשו באחת מאלה:

  • התחלת משתמשים באפשרות 1M: הגדירו modelPrefer1mContext: true בבלוק desktop של המדיניות. משתמשים שעדיין לא בחרו מודל מתחילים באפשרות 1M כשלמודל הראשון ברשימה יש אחת. משתמשים שכבר בחרו מודל שומרים על הבחירה שלהם.
  • הצעת האפשרות ידנית: עשו זאת אם שרת השער שלכם מריץ גרסה ישנה מ-v2.1.284, או שרשומה לא מציינת מודל Claude. רשמו את המודל פעמיים ב-models, פעם עם ה-ID הפשוט ופעם עם [1m] מצורף, שתיהן עם אותה מפת upstream_model. Claude Desktop מציג את הזוג כמודל אחד עם אפשרות 1M. השער מגיש רשומת [1m] בלי לבדוק אותה, לכן הוסיפו אחת רק למודל שה-upstreams שלכם מגישים ב-1M.

הדוגמה הזו מציעה את האפשרות ידנית לכינוי מותאם שמנותב לפרופיל הסקה של אפליקציה, ומתחילה משתמשים חדשים עליה:

models:
  - id: corp-sonnet
    upstream_model:
      bedrock: arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/sonnet-5-prod
  - id: corp-sonnet[1m]
    upstream_model:
      bedrock: arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/sonnet-5-prod

managed:
  policies:
    - match: {}
      desktop:
        modelPrefer1mContext: true
#הסרת אפשרות 1M

כדי להסיר את האפשרות מהבורר, הגדירו CLAUDE_CODE_DISABLE_1M_CONTEXT: "1" בבלוק env תחת מפתח cli של המדיניות. אם גם רשמתם רשומה שה-id שלה מסתיים ב-[1m], השער עדיין מגיש אותה, לכן מחקו גם את הרשומה הזו.

המשתנה גם מגיע להפעלות הטרמינל של מפתחים שהמדיניות תואמת להם. למה הוא משנה שם, ראו הקשר מורחב.

#קדימות מול מקורות מנוהלים אחרים

אם למכשיר יש גם מדיניות שנמסרה ב-MDM או managed-settings.json מקומי, הגדרות שהשער מסר מדורגות ראשונות. קדימות בתוך השכבה המנוהלת בדף ההגדרות המנוהלות אומר מתי המקורות המקומיים חלים, ויש בו את המפתחות ש-Claude Code קורא מכל מקור ניהול בלי קשר למקור שבחר, כמו מפתחות נעילת ארגז החול, forceRemoteSettingsRefresh, ומיזוג env לפי משתנה. policyHelper שמוגדר בפרופיל MDM או בקובץ ההגדרות המנוהלות רץ רק כשהשער לא מספק הגדרות. הרשומה אומרת מה הפלט שלו מחליף.

מארחים מטמיעים כמו Claude Desktop יכולים לספק מדיניות דרך אפשרות managedSettings של ה-SDK. הגדרות הורה ממארחים מטמיעים אומר מתי Claude Code מחיל אותן, והגבלת הגדרות הורה מפרטת אילו הגדרות בכיוון היתר עדיין חלות בלי נעילות allowManaged*Only.

מדיניות השער חלה על כל הפעלה של Claude Code במכונה, כולל הרצות claude -p לא אינטראקטיביות והפעלות שה-Agent SDK יוצר. אם השער לא נגיש בהפעלה, הפעלות מחוברות יוצאות עם שגיאה במקום לרוץ בלי המדיניות שלהן.

#telemetry

ה-CLI שולח מדדים, לוגים, וכשהאפשרות מופעלת גם traces, אל ה-gateway, שמעביר אותם כלשונם לכל יעד מוגדר. הייצואים משתמשים ב-OpenTelemetry Protocol (OTLP) מעל HTTP. כדי לדלג על הממסר ולגרום לסשנים לייצא ישירות אל ה-collector שלך, ציין את שם ה-collector במדיניות. ראה Monitoring usage למדדים ולאירועים שה-CLI פולט.

בסשנים שנכנסו דרך /login, ה-CLI חותם כל ייצוא בזהות המשתמש המאומת, שנקראת מ-JWT שה-gateway הנפיק: המאפיינים user.id, user.email ו-user.groups. לכן ייחוס עלות ושימוש לכל מפתח עובד בלי הגדרה מצד המפתח. אירועים ש-Claude Code רושם לפני שהמפתח נכנס לא נושאים את הזהות הזו. כדי לראות איזה מאפיין עוקב אחרי שינוי בקבוצות של מפתח, ראה שינויי קבוצות במהלך סשן פתוח.

סשנים של Claude Desktop ושל Cowork שנכנסו דרך ה-gateway חותמים את ה-telemetry שלהם ב-user.email וב-user.groups לצד enduser.id, כך שאפשר לכסות שימוש בטרמינל, ב-Desktop וב-Cowork בשאילתה אחת על user.email או על user.groups. user.groups הוא רשימת קבוצות ה-IdP מופרדת בפסיקים.

telemetry של Desktop ושל Cowork נושא גם את enduser.sub, ה-claim sub שספק הזהות שלך מנפיק למשתמש, והוא נשאר זהה כשכתובת האימייל של משתמש משתנה. סשני טרמינל חותמים את אותו ערך תחת user.id, כך ששאילתה שמתאימה את enduser.sub מול user.id של טרמינל מכסה יחד את השימוש של משתמש אחד בטרמינל, ב-Desktop וב-Cowork. בייצואים של Desktop ושל Cowork, user.id הוא מזהה אנונימי, לא ה-subject.

כמו כל נתוני OpenTelemetry מ-Claude Code, המאפיינים האלה הולכים רק ליעדים שהארגון שלך מגדיר, ולעולם לא ל-Anthropic.

אם רשימת הקבוצות של משתמש ארוכה מ-255 תווים אחרי percent-encoding, או ששם קבוצה מכיל פסיק או סימן שוויון, ה-gateway משמיט את user.groups מ-telemetry של Desktop ושל Cowork של אותו משתמש במקום לקצץ אותו. סשני הטרמינל של אותו משתמש עדיין נושאים את הרשימה המלאה.

ה-gateway משמיט את enduser.sub כשה-subject ארוך מ-255 תווים אחרי percent-encoding, או מכיל רווח, תו מחוץ ל-ASCII להדפסה, או אחד מבין , ; = \ " %. ה-telemetry של Desktop ושל Cowork של אותו משתמש שומר על שאר המאפיינים שלו.

נדרש Claude Code v2.1.265 או חדש יותר בשרת ה-gateway כדי לקבל user.email ו-user.groups ב-telemetry של Desktop ושל Cowork, ו-Claude Desktop 1.24012 או חדש יותר בכל מחשב של מפתח כדי לקבל user.groups.

נדרש Claude Code v2.1.274 או חדש יותר בשרת ה-gateway כדי לקבל enduser.sub.

telemetry:
  forward_to:
    - url: https://otel-collector.internal.example.com
      headers:
        Authorization: ${OTLP_TOKEN}
      # Per-signal opt-in. Default: metrics only.
      metrics: true
      logs: false
      traces: false
    - url: https://api.datadoghq.com/api/v2/otlp
      headers:
        DD-API-KEY: ${DD_API_KEY}

[!WARNING]

כל יעד בוחר בנפרד ב-metrics, ב-logs וב-traces, וברירת המחדל היא מדדים בלבד. האותות נבדלים ברגישות:

  • Metrics: מונים מצטברים כגון ספירות טוקנים, ספירות בקשות וזמן תגובה
  • Logs and traces: יכולים לשאת פקודות Bash מלאות, קלטי כלים ונתיבי קבצים, ולכסות כל דבר ש-Claude Code עושה במחשב של מפתח

הפעל לוגים ו-traces רק ביעדים עם בקרות הגישה ומדיניות השמירה שהנתונים האלה מצדיקים.

כל כתובת URL של forward_to חייבת להשתמש ב-https://, עם חריג אחד ל-collector על ממשק ה-loopback של ה-gateway עצמו:

  • http://localhost:<port> עובר אימות הגדרות, אבל מנגנון ההגנה מפני SSRF חוסם כל ייצוא עם ECONNREFUSED_SSRF אלא אם מגדירים CLAUDE_GATEWAY_ALLOW_LOOPBACK=1 בסביבה של ה-gateway
  • http://127.0.0.1:<port> או http://[::1]:<port> נכשל בעלייה אלא אם המשתנה הזה מוגדר

ל-collector בתוך האשכול, חשוף אותו מעל HTTPS בכתובת הפנימית שלו, או הרץ אותו כ-sidecar כשהמשתנה מוגדר.

כש-HTTPS_PROXY מוגדר, ה-gateway שולח ייצואים דרך אותו proxy.

כדי להגיע ל-collector פנימי ישירות, הוסף אותו ל-NO_PROXY לפי hostname או לפי דומיין עם נקודה מובילה כגון .internal.example.com, מה שדורש Claude Code v2.1.277 או חדש יותר בשרת ה-gateway. ודא שה-gateway יכול להגיע ל-collector בלי ה-proxy. רשומה בלי נקודה מובילה מתאימה רק לאותו שם מדויק, לא לשמות שמתחתיו. טווחי CIDR לא מתאימים.

כש-יציאה דרך proxy בלבד מופעלת, אפשר את ה-collector ב-proxy במקום זאת, כי כל רשומת NO_PROXY משאירה את היציאה דרך proxy בלבד כבויה.

telemetry כבוי ב-CLI כברירת מחדל. כשמגדירים גם את telemetry.forward_to וגם את listen.public_url, ה-gateway מפעיל אותו ללקוחות מחוברים על ידי דחיפת שישה משתני סביבה דרך /managed/settings:

  • CLAUDE_CODE_ENABLE_TELEMETRY=1
  • OTEL_METRICS_EXPORTER, OTEL_LOGS_EXPORTER ו-OTEL_TRACES_EXPORTER, כל אחד מוגדר ל-otlp אם לפחות יעד forward_to אחד מפעיל את האות הזה, ול-none אחרת
  • OTEL_EXPORTER_OTLP_ENDPOINT=<public_url>
  • OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf

כש-מוסיפים תוויות משלך, ה-gateway דוחף גם את OTEL_RESOURCE_ATTRIBUTES.

לפני Claude Code v2.1.265 בשרת ה-gateway, ה-gateway דחף את שלושת בוררי ה-exporter כ-otlp, כולל לאותות שאף יעד לא בחר בהם.

נקודת הקצה שנדחפת נבנית מכתובת ה-URL הציבורית, כך שמדדים ולוגים לא דורשים הגדרת OTEL ממפתחים או ממדיניות.

מפתחים שנכנסו דרך /login לא יכולים להפנות ייצואים מחדש עם הגדרת OTEL משלהם:

  • משתנים שהוגדרו מקומית: Claude Code מחיל את המשתנים שנדחפו בשכבת managed, כך שכל אחד מהם דורס את הערך שמפתח מגדיר לו מקומית.
  • נקודות קצה שהוגדרו מקומית: כשייצוא OTLP/HTTP מופעל, ה-CLI מתעלם מכל נקודת קצה שהוגדרה מקומית, בין שה-gateway דחף את משתני ה-telemetry ובין שלא. הייצואים שלו הולכים אל ה-gateway אלא אם מדיניות מציינת את ה-collector שלך כנקודת הקצה.

בלי יעד forward_to לאות, ה-gateway מקבל אותו ומשליך אותו. אם מפתחים כבר מייצאים telemetry של Claude Code לאחד מה-collectors שלך, הוסף אותו כיעד forward_to, עם לוגים או traces מופעלים אם הם מייצאים אותם, כדי שהוא ימשיך לקבל את הנתונים שלהם אחרי שהם נכנסים. כדי לדלג על הממסר במקום זאת, ציין את שם ה-collector במדיניות.

Traces דורשים גם CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1 בכל לקוח. הגדר אותו בבלוק env של מדיניות managed, כי ה-gateway לא דוחף אותו. מפתחים מאשרים אותו באותה תיבת אישור אבטחה שנקודת הקצה שנדחפה כבר מפעילה.

הגדר אותו ל-1 רק במדיניות של הקבוצות שרוצים לעקוב אחריהן ב-traces. מדיניות שלא מגדירה אותו יורשת את הערך ממדיניות ה-catch-all match: {} שלך אם המדיניות הזו מגדירה אחד, לפי כללי המיזוג. כדי למנוע מלקוחות של קבוצה לשלוח traces גם כשמפתח מגדיר את המשתנה מקומית, הגדר אותו ל-0 במדיניות של אותה קבוצה.

גם קידוד OTLP ב-protobuf וגם קידוד ב-JSON מועברים, וכל backend תואם OpenTelemetry עובד כיעד.

#שליחת מדדים מצטברים

אם ה-collector שלך מקבל רק מדדים מצטברים, הגדר את OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE ל-cumulative. Claude Code שולח מדדי delta כברירת מחדל, וה-gateway מעביר אותם בלי להמיר אותם. הגדר את המשתנה במקום שבו כל סוג סשן קורא אותו:

אם מוסיפים את המשתנה להגדרות managed של מחשב, הגדר גם parentSettingsBehavior: "merge" במקור בעדיפות הגבוהה ביותר באותו מחשב. בלעדיו, סשני Cowork וסשני לשונית Code תחת מדיניות cli רצים בלי רשימת ההיתר ליציאה ובלי מדיניות אחרת ש-Claude Desktop מעביר להם כהגדרות הורה.

#הוספת תוויות משלך

כדי לשים תוויות קבועות כגון service.namespace או deployment.environment.name על ה-telemetry של סשנים שנכנסו דרך ה-gateway, הגדר את telemetry.resource_attributes. כל תווית היא מאפיין resource של OpenTelemetry, וכל יעד מקבל את אותן תוויות.

סשנים מקבלים את התוויות רק כשמגדירים גם את telemetry.forward_to וגם את listen.public_url. הדוגמה הזו מוסיפה שתי תוויות:

telemetry:
  forward_to:
    - url: https://otel-collector.internal.example.com
  resource_attributes:
    service.namespace: claude
    deployment.environment.name: prod

ה-gateway מסרב לעלות כשתווית שוברת אחד מהכללים האלה, ושגיאת העלייה מציינת את שם התווית:

  • שמות משתמשים רק באותיות, בספרות, ב-., ב-_ וב--
  • שמות אינם שמורים. בהשוואה בכל מצב אותיות, השמות השמורים הם כל מה שמתחיל ב-user., ב-enduser. או ב-identity., ועוד service.name, service.version, claude.deployment_mode, host.arch, os.type, os.version ו-wsl.version
  • ערכים הם ASCII להדפסה לא ריק, בלי רווח ובלי אף אחד מבין , ; = \ " %
  • ערכים הם לכל היותר 255 תווים כפי שה-gateway סופר אותם אחרי percent-encoding, כך ש-/, : ו-@ נספרים כל אחד כשלושה
  • ערכים הם טקסט, אז צטט מספר, true או false

נדרש Claude Code v2.1.281 או חדש יותר בשרת ה-gateway כדי להגדיר את telemetry.resource_attributes. gateway מוקדם יותר מסרב לעלות כשהוא מוצא את המפתח. שדרג כל replica לפני שמוסיפים את המפתח, והסר את המפתח לפני שמחזירים גרסה מוקדמת יותר.

סשני טרמינל שנכנסו דרך /login מקבלים את התוויות כ-OTEL_RESOURCE_ATTRIBUTES, שנדחף עם שאר משתני ה-telemetry. אם מגדירים את OTEL_RESOURCE_ATTRIBUTES בבלוק env של מדיניות, סשני טרמינל שהמדיניות הזו מתאימה להם מקבלים את הערך הזה במקום התוויות. Claude Desktop מקבל את התוויות מה-gateway לצד user.email ושאר מאפייני הזהות.

Claude Code גם מעתיק כל תווית אל כל נקודת נתונים של מדד, כך שאפשר לסנן מדדים לפיה ב-backend שלא מאנדקס מאפייני resource. כדי לכבות את ההעתקה הזו, ראה Metrics cardinality control.

#שינויי קבוצות במהלך סשן פתוח

סשני טרמינל שמים את user.groups על ה-resource של OTLP ושוב על כל נקודת נתונים של מדד ועל כל אירוע. אם הקבוצות של מפתח משתנות בזמן שסשן פתוח, נקודות נתונים ואירועים לשימוש שאחרי ה-רענון השקט הבא נושאים את הקבוצות החדשות. ה-resource שומר את הקבוצות הישנות עד שהמפתח מפעיל מחדש את Claude Code, אז קבץ לפי המאפיין על נקודת הנתונים או על האירוע.

אם מפעילים את resource_to_telemetry_conversion ב-exporter של Prometheus remote write ב-OpenTelemetry Collector, ה-exporter מחליף את user.groups של כל נקודת נתונים בזה של ה-resource, כך שכל נקודת נתונים מציגה את הקבוצות הישנות. כדי לשמור את הערך של נקודת הנתונים, מחק את user.groups מה-resource לפני אותו exporter.

מעבד resource זה של OpenTelemetry Collector מוחק את המאפיין ב-pipelines שמציינים אותו:

processors:
  resource/drop-user-groups:
    attributes:
      - key: user.groups
        action: delete

אחרי שמוסיפים את resource/drop-user-groups ל-processors של pipeline המדדים, כל series נושא את תווית user_groups מנקודת הנתונים שלו.

#ייצוא ישיר אל ה-collector שלך

כדי שסשנים שנכנסו דרך /login ישלחו telemetry ישירות אל ה-collector שלך במקום דרך הממסר, הגדר את OTEL_EXPORTER_OTLP_ENDPOINT לכתובת הבסיס https:// של ה-collector בבלוק env של מדיניות managed. Claude Code מוסיף /v1/metrics, /v1/logs או /v1/traces לכתובת שאתה מגדיר, כגון https://otel-collector.example.com:4318, ומייצא כל אות לשם מעל OTLP/HTTP. נדרש Claude Code v2.1.265 או חדש יותר בכל מחשב של מפתח. לקוחות מוקדמים יותר מייצאים דרך הממסר.

כדי לאמת מול ה-collector, הגדר את OTEL_EXPORTER_OTLP_HEADERS באותו בלוק env. סשנים לעולם לא שולחים את טוקן הסשן של המפתח ב-gateway אל collector ששמו צוין כך.

כשמוסיפים או משנים את נקודת הקצה הזו במדיניות, Claude Code מבקש מכל מפתח לאשר אותה בתיבת אישור האבטחה לפני שהוא מחיל אותה בסשן אינטראקטיבי.

Claude Code בודק את נקודת הקצה לפני שהוא מייצא אות ישירות, ומשאיר את האות על הממסר כשבדיקה נכשלת. הבדיקות כוללות:

  • נקודת הקצה מגיעה מה-gateway עצמו. אם מגדירים את אותו משתנה בפרופיל MDM או ב-managed-settings.json מקומי, הייצואים נשארים על הממסר.
  • כתובת ה-URL משתמשת ב-https://, או ב-http:// אל כתובת loopback
  • כתובת ה-URL נפתרת לנתיב שמסתיים ב-/v1/<signal>, בלי query או fragment. Claude Code בונה את הנתיב הזה בעצמו מהמשתנה הגנרי. הוא משתמש במשתנה לפי אות כגון OTEL_EXPORTER_OTLP_METRICS_ENDPOINT כפי שנכתב, אז כלול שם את הנתיב המלא.
  • כתובת ה-URL אינה המארח של ה-gateway עצמו. נקודת קצה שמופנית אל ה-gateway שומרת על נתיב הממסר ועל טוקן הסשן שלו.
  • לא אתה ולא המפתח הגדרתם otelHeadersHelper באף מקור הגדרות. כש-helper מוגדר, כל אות נשאר על הממסר.

נקודת הקצה שאתה מציין משנה רק לאן הייצואים הולכים. עדיין בוחרים אילו אותות מיוצאים בכלל עם בוררי OTEL_*_EXPORTER.

נקודת הקצה לבדה לא מפעילה ייצוא, אז הגדר גם את המשתנים שכן מפעילים, אלא אם ה-gateway כבר דוחף אותם:

  • אם ה-gateway כבר דוחף את משתני ה-telemetry, הם מכסים הפעלה, בוררים ופרוטוקול, ונקודת הקצה המפורשת שלך דורסת את ערך <public_url> שנדחף. הגדר בורר OTEL_*_EXPORTER ל-otlp בעצמך רק לאות שאף יעד forward_to לא מפעיל.
  • אם הוא לא דוחף, הגדר גם את CLAUDE_CODE_ENABLE_TELEMETRY=1, את בוררי OTEL_*_EXPORTER ואת OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf.

כשהמפתח יוצא, או נכנס ל-gateway אחר, הייצואים אל ה-collector נעצרים ו-Claude Code משליך כל batch שנותר במקום לשלוח אותו.

#כשיעד נכשל

ה-gateway לא מאגר, לא מנסה שוב ולא שומר telemetry, אז הוא משליך ייצוא שלא מגיע ליעד במקום למסור אותו באיחור. כל יעד מצליח או נכשל בפני עצמו, והלקוח המייצא מקבל תגובת הצלחה בכל מקרה, כך שמסירה שנכשלה מופיעה רק בלוג של ה-gateway.

אחרי חמש מסירות כושלות רצופות ליעד, ה-gateway משהה העברה אליו במקטעים של 30 שניות, ורושם כל השהיה בלוג, עד שמסירה מצליחה. כל תגובת שגיאה, timeout או שגיאת חיבור נספרים כמסירה כושלת, חוץ מ-400, 413, 415, 422 ו-431, שמשמעותם שה-collector סירב למטען של אותו ייצוא כי הוא פגום או גדול מדי.

מטען שנדחה לא מקדם ולא מאפס את מונה הכשלונות: ה-gateway ממשיך להעביר אל היעד ורושם אזהרה שמציינת אותו ואת הסטטוס, בסירוב הראשון של היעד ובכל מאה אחריו.

#כוונון HTTP

ארבעה בלוקים אופציונליים ברמה העליונה, access_control, limits, timeouts ו-rate_limits, מכווננים את משטח ה-HTTP. ברירות המחדל מתאימות לרוב הפריסות.

בלוקמפתחברירת מחדלתיאור
access_controlallow_cidrs / deny_cidrsריקהיתר או דחייה של IP נכנס לפי כתובת הלקוח, אחרי פתרון trusted_proxies. deny_cidrs נבדק ראשון. לקוח שהוא תואם נדחה גם אם allow_cidrs תואם גם כן. אם allow_cidrs אינו ריק, השער דוחה כברירת מחדל. /healthz ו-/readyz פטורים מ-allow_cidrs. כשפרוקסי מהימן שולח רשומת X-Forwarded-For שאינה כתובת IP, הלקוח האמיתי אינו ידוע והשער רושם אזהרה פעם אחת שמציינת מה לבדוק. במקום שבו אחת מהרשימות חלה על הבקשה, הוא מסרב לה עם 403 וסיבת ביקורת xff_unparseable. במקום שבו אף אחת לא חלה, הוא מגיש את הבקשה ומשתמש בכתובת של הפרוקסי עצמו ככתובת ה-IP של הלקוח למגבלות קצב לפי IP ולביקורת.
limitsmax_request_bytes32 MiBגוף בקשה נכנס מרבי. בקשות גדולות מדי מקבלות 413 לפני שהגוף נשמר בחוצץ. העלו עבור בקשות קובץ או תמונה גדולות.
limitsmax_request_header_bytesלא מוגדרמוריד את מגבלת השער של 256 KiB על סך הכותרות של בקשה. בקשה מעל המגבלה מחזירה 431, וערך מעל 256 KiB אינו משפיע. אם מפתחים מקבלים 431 אחרי כניסה, ראו כותרות בקשה גדולות מדי אחרי כניסה.
limitsmax_url_lengthלא מוגדרכשהוא מוגדר, כתובת URL ארוכה מדי מחזירה 414
timeoutsupstream_ttfb_ms120000המתנה מרבית לכותרות התגובה של ה-upstream (זמן עד הבייט הראשון). גוף התגובה אחר כך מוזרם בלי תקרת שעון קיר. אם המפתח אינו מוגדר, ברירת המחדל חלה על upstreams של provider: anthropic, ובכל ספק אחר השער ממתין עד שעה אחת עד שהתגובה מתחילה. כדי לקצר את ההמתנה הזו, ראו upstreams מרובים.
rate_limitsdevice_authorization.max / .window_seconds30 / 600מגבלת קצב לפי IP על נקודת הקצה הלא מאומתת של device-authorization. העלו עבור ארגון גדול מאחורי IP יציאה משותף או NAT. פריסות גדולות מראה איך לגודל אותה. המגבלות האלה חלות רק על זרימת הכניסה של device-grant, לא על הסקה של /v1/messages. ראו עמידות בפני brute-force של קוד משתמש.
rate_limitsdevice_verify.max / .window_seconds10 / 600מגבלת קצב לפי IP על הגשות user_code ב-/device. זה מה שעוצר מישהו מניחוש הקוד של מפתח אחר. פריסות גדולות מראה עד כמה להעלות אותה.

אם משאירים את שתי רשימות access_control ריקות, וזו ברירת המחדל, השער מגיש כל כתובת לקוח, כך שרק הרשת שלכם מגבילה מי יכול להגיע אליו. זה חשוב כי שער יכול לדחוף הגדרות מנוהלות שמריצות פקודות על מכונות של מפתחים.

בזמן ש-allow_cidrs ריק, השער מזהיר בשני מקומות, בלי לשנות איך הוא עונה לכל בקשה:

  • בעלייה: אזהרה ביומן התפעולי ממליצה לאפשר רק את הטווחים הפרטיים 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 100.64.0.0/10, 127.0.0.0/8, ::1/128 ו-fc00::/7, ועוד כל טווח פנימי אחר שממנו המפתחים שלכם מתחברים. אם קושרים את השער לכתובת loopback ולא מגדירים לא trusted_proxies ולא public_url, כמו בפיתוח מקומי, האזהרה לא מופיעה.
  • בזמן ריצה: בפעם הראשונה שמגיעה בקשה מכתובת מחוץ לטווחים הפרטיים האלה, השער רושם אזהרה ופולט אירוע ביקורת access.public_client שנושא את ה-IP של הלקוח. שניהם נורים פעם אחת לכל תהליך. כתובות link-local, 169.254.0.0/16 ו-fe80::/10, לא נחשבות ציבוריות. השער עונה ל-/healthz ול-/readyz לפני שהבדיקה הזו רצה, כך שבדיקות תקינות מטווחים ציבוריים לא מפעילות אותה.

שני האותות משתמשים בכתובת הלקוח כפי שהשער פותר אותה. אם מאזן עומסים, port-forward או מנהרה מעבירים תעבורה ואינם רשומים ב-listen.trusted_proxies, השער רואה את כתובת הממסר, שבדרך כלל פרטית, כך שלא האזהרה בזמן ריצה ולא רשימת היתר פרטית תופסות תעבורה שמועברת דרכו.

מאחורי חזית כזו, הגדירו קודם listen.trusted_proxies כדי שהשער יראה כתובות לקוח אמיתיות, ושמרו על כך שהשער וכל מה שלפניו לא יהיו נגישים מהאינטרנט הציבורי בכל מקרה.

#load_test_mode

בלוק load_test_mode מאפשר לבדוק עומס על שער בלי לקרוא לספק מודל. בזמן שהוא פועל, השער בונה וחותם כל בקשת ספק כרגיל, משליך אותה במקום לשלוח אותה, ומזרים תשובה מוכנה מראש בחזרה דרך נתיב התגובה הרגיל שלו. התשובה היא טקסט מילוי שמתחיל במשפט שאומר שהיא מוכנה מראש.

דורש Claude Code v2.1.282 או חדש יותר על שרת השער. שער מוקדם יותר מסרב לעלות כשהוא מוצא את המפתח. שדרגו כל רפליקה לפני שמוסיפים את הבלוק, והסירו את הבלוק לפני חזרה לאחור.

הדוגמה למטה מפעילה את המצב עם ברירות המחדל, תשובה של בערך 750 טוקנים של טקסט שמוזרמת על פני כ-10 שניות:

load_test_mode:
  enabled: true
  reply_tokens: 750     # roughly how many tokens of text each canned reply carries
  reply_seconds: 9.5    # how long a streamed reply takes
שדהנדרשתיאור
enabledכןtrue מפעיל את המצב. false שומר את המספרים שלכם בקובץ עם המצב כבוי. השער מסרב לעלות אם הבלוק קיים בלעדיו.
reply_tokensלאברירת מחדל 750. בערך כמה טוקנים של טקסט כל תשובה מוכנה מראש נושאת, מספר שלם מ-1 עד 100000.
reply_secondsלאברירת מחדל 9.5. כמה זמן תשובה מוזרמת נמשכת, מ-0 עד 600. 0 שולח את כל התשובה בבת אחת. תשובה לבקשה שאינה streaming תמיד חוזרת בבת אחת.

בדיקת עומס במצב הזה מכסה את השער, את Postgres שלכם, וכל מה שלפני השער. היא לא מכסה את המגבלות, המהירות ונתיב הרשת של הספק, או את ההמתנה ב-מגבלה על בקשות upstream מקבילות של כל רפליקה. רפליקה עדיין רושמת את האזהרה client requests are open כשיש יותר בקשות פתוחות מהמגבלה הזו, הנקודה שבה בקשות ייצור מתחילות להמתין.

אף בקשת מודל לא נשלחת לספק, כך שה-CPU של רפליקה לכל בקשה הוא אומדן ונמדד נמוך יותר מאשר בייצור, שגם מצפין את התעבורה שלו אל הספק. אשרו מספר רפליקות עם פיילוט קטן מול הספק האמיתי. לפני v2.1.283, האומדן נמדד נמוך בהרבה.

בזמן שהמצב פועל, בקשה יכולה לשאת כותרת x-load-test-user שמחזיקה מספר שלם של עד שבע ספרות. השער סופר כל מספר כמפתח נפרד, עם הדוא"ל והקבוצות של המפתח שהטוקן שלו הגיע עם הבקשה.

תנו לפריסת בדיקת העומס מסד נתונים ריק משלה, כי השער מסרב לעלות עם המצב פועל מול מסד נתונים שבו מפתח כלשהו כבר הוציא משהו.

[!WARNING]

לעולם אל תפעילו את זה על שער שמפתחים משתמשים בו. כל בקשה מקבלת את התשובה המוכנה מראש ואין קריאה למודל. השער רושם אזהרת load_test_mode is on בעלייה ומסמן כל אירוע ביקורת inference עם load_test: true בזמן שהמצב פועל.

#דוגמה מלאה

הגדרת הייחוס המלאה הזו מפעילה כל מקטע ליבה. בלוקי כוונון ה-HTTP שומרים על ברירות המחדל שלהם. העתיקו אותה, מחקו מה שלא צריך, ומלאו את הערכים שלכם. ההגדרה ב-התחלה מהירה היא גרסה מינימלית של זה.

# Run with:
#   claude gateway --config gateway.yaml
#
# Operational log verbosity is controlled by the CLAUDE_GATEWAY_LOG_LEVEL
# environment variable (debug | info | warn | error; default info). debug
# also logs the claim names in each id_token, for groups_claim diagnosis.
# It does not affect audit events, which are always emitted.

listen:
  host: 0.0.0.0
  port: 8080
  public_url: https://claude-gateway.internal.example.com
  # Omit the tls block when running behind a TLS-terminating ingress.
  # tls:
  #   cert: /certs/gateway.crt
  #   key: /certs/gateway.key
  # trusted_proxies:
  #   - 10.0.0.0/8

oidc:
  issuer: https://example.okta.com
  client_id: 0oa1example2
  client_secret: ${OIDC_CLIENT_SECRET}
  allowed_email_domains:
    - example.com
  # Required when the issuer is the Okta org server, whose id_tokens
  # can omit email and groups; the gateway fills them from /userinfo.
  userinfo_fallback: true
  # allowed_groups: [claude-code-users]
  # Okta emits groups only when the `groups` scope is requested and the
  # app's groups claim filter allows them. The contractors policy below
  # matches on groups, so the scope is requested here.
  scopes: [openid, profile, email, offline_access, groups]
  # extra_auth_params: { access_type: offline, prompt: consent }  # Google
  # groups_claim: groups          # Entra app roles: use `roles`
  # email_claim: email

session:
  jwt_secret: ${GATEWAY_JWT_SECRET}   # openssl rand -base64 32
  # ttl_hours: 1

store:
  postgres_url: ${GATEWAY_POSTGRES_URL}
  # max_connections: 5
  # connect_timeout_seconds: 5
  # readiness_grace_seconds: 300   # keep passing the readiness check through a database failover

# Enables /v1/organizations/spend_limits (mirrors the Anthropic Admin API)
# and per-developer spend enforcement on /v1/messages. Omit to disable.
# Caps themselves are set via the admin API, not here.
# admin:
#   write_keys:
#     - { id: terraform, key: "${GATEWAY_ADMIN_WRITE_KEY_TF}" }
#   read_keys:
#     - { id: reporting, key: "${GATEWAY_ADMIN_READ_KEY}" }
#   admin_groups: [platform-finops]
#   blocked_message: request an increase at https://go.example.com/claude-limits
#   # audit_retention_days: 365
#   # spend_retention_months: 13
#   # identity_retention_days: 90
#   # group_limit_mode: min

# enforcement:
#   fail_closed_on_error: false

# Load test this deployment without calling a model provider. Never on a
# gateway that developers use: every request gets a canned reply.
# load_test_mode:
#   enabled: true
#   # reply_tokens: 750
#   # reply_seconds: 9.5

# Meter at contracted rates instead of USD list price. Requires admin: or a
# managed: policy. With managed:, the same rates also go to signed-in clients.
# Rates below are placeholders, not real contract prices.
# pricing:
#   multiplier: 0.85
#   overrides:
#     - { upstream: anthropic, model: claude-sonnet-4-6, input: 3.30, output: 16.50, cache_read: 0.33, cache_write: 4.125 }

upstreams:
  - provider: anthropic
    auth:
      api_key: ${ANTHROPIC_API_KEY}

  # - provider: bedrock
  #   region: us-east-1
  #   auth: {}

  # - provider: mantle
  #   region: us-east-1
  #   models: [claude-opus-4-8, claude-opus-4-7, claude-haiku-4-5]
  #   auth: {}

  # - provider: anthropicAws
  #   region: us-east-1
  #   workspace_id: wrkspc_...
  #   auth:
  #     api_key: ${ANTHROPIC_AWS_API_KEY}

  # - provider: vertex
  #   region: us-east5
  #   project_id: example-prod
  #   auth: {}

  # - provider: foundry
  #   resource: example-foundry
  #   auth: { use_azure_ad: true }

auto_include_builtin_models: true
models:
  - id: claude-opus-4-8
    label: Claude Opus 4.8
    upstream_model:
      anthropic: claude-opus-4-8
      # bedrock: us.anthropic.claude-opus-4-8
      # mantle: anthropic.claude-opus-4-8
      # anthropicAws: claude-opus-4-8
      # vertex: claude-opus-4-8
      # foundry: <your-opus-deployment-name>
  - id: claude-sonnet-4-6
    label: Claude Sonnet 4.6
    upstream_model:
      anthropic: claude-sonnet-4-6
  - id: claude-haiku-4-5
    label: Claude Haiku 4.5
    upstream_model:
      anthropic: claude-haiku-4-5

managed:
  policies:
    - match: { groups: [contractors] }
      cli:
        availableModels: [claude-haiku-4-5]
        # allow auto-approves these tools; it does not block the rest.
        # Add deny rules to restrict tools.
        permissions: { allow: [Read, Grep] }
    - match: {}
      cli:
        availableModels: [claude-opus-4-8, claude-sonnet-4-6, claude-haiku-4-5]
        # Constrain the Default picker option to each policy's availableModels
        # instead of the built-in default, so no role gets a 400 on Default.
        # The contractors policy inherits this key.
        enforceAvailableModels: true
        permissions:
          allow: [Read, Grep, Edit]
          deny: ["WebFetch"]
        env: { HTTP_PROXY: http://proxy.example.com:8080 }

telemetry:
  forward_to:
    - url: https://otel.internal.example.com:4318
      headers:
        Authorization: Bearer ${OTEL_TOKEN}

#הגדרות מנוהלות בצד הלקוח

כל מה שלמעלה מגדיר את שרת השער. מכוונים את מכונות המפתחים אל השער בנפרד, על כל מכשיר, דרך ההגדרות המנוהלות של Claude Code. השער לא יכול לדחוף את מפתחות הכניסה בעצמו, כי הם אלה שאומרים ללקוח איפה השער נמצא.

עבור ה-CLI, הגדירו את המפתחות האלה ב-managed-settings.json לפי מערכת ההפעלה. שני מפתחות הכניסה מנתבים את /login של כל מפתח אל השער שלכם:

{
  "forceLoginMethod": "gateway",
  "forceLoginGatewayUrl": "https://claude-gateway.internal.example.com",
  "parentSettingsBehavior": "merge"
}

parentSettingsBehavior: "merge" שומר על כך שהעברת רשימת ההיתר של היציאה מ-Claude Desktop אל הפעלות Claude Code המוטמעות שלו תעבוד. מסירת מדיניות להפעלות Claude Desktop מסביר את המנגנון ואיפה ההצטרפות חייבת לשבת.

כדי לעצור מפתחים מלעקוף את השער עם משתנה של ספק ענן או ANTHROPIC_BASE_URL משלהם, הוסיפו "allowedProviders": ["gateway"] לאותו קובץ. Claude Code אז מסרב לכל הפעלה במכונה שלא מוגדרת לשער Cloud, ומאשר שער רק כשהוא זה ש-forceLoginGatewayUrl מציין או אחד שכתובת ה-URL שלו מוגדרת בבלוק env של הקובץ כ-ANTHROPIC_BASE_URL. claude gateway מסרב לרוץ על מכונה שמגדירה את הרשימה, אז השאירו את המפתח מחוץ למארח השער. ראו את הערך allowedProviders בייחוס ההגדרות. דורש Claude Code v2.1.285 או חדש יותר.

פרסו את קובץ managed-settings.json לכל מכשיר, בדרך כלל דרך פלטפורמת ה-MDM שלכם. נתיב הקובץ שונה לפי פלטפורמה. ראו איפה כל מנגנון שומר את המדיניות.

כברירת מחדל, מדיניות registry ב-Windows או plist של managed-preferences ב-macOS מחליפים את קובץ managed-settings.json במקום להתמזג איתו, מלבד מפתחות החריגה ובדיקות בין מקורות למעלה. כל שלושת המפתחות בקטע הזה עוקבים אחרי כלל המקור בעדיפות הגבוהה ביותר, כך שציים שמספקים מדיניות דרך Group Policy או פרופילי תצורה חייבים לשים את שלושתם במנגנון הזה במקום.

עבור Claude Desktop, הגדירו את המפתח bootstrapUrl ב-תצורה המנוהלת של Claude Desktop עצמו ל-<listen.public_url>/user/bootstrap. זרימת הכניסה והמדיניות לפי קבוצה אז תואמות לאלה של ה-CLI אחרי שמדיניות מצטרפת בצד השרת עם מפתח desktop. בלי ההצטרפות, /user/bootstrap מחזיר 404. ראו שכבת Claude Desktop לחצי שבצד השרת.

Claude Code מכבד את forceLoginGatewayUrl, gatewayInternalNetworks, ואת הערך "gateway" של forceLoginMethod ממקור מנוהל במכונה: managed-settings.json, ה-plist של macOS או ה-registry של Windows HKLM, או עוזר מדיניות. הגדרתם ב-payload של השער לא מגדירה את כניסת השער. עבור ~/.claude/settings.json של מפתח עצמו, ראו הגדרת כתובת ה-URL של השער בהגדרות המשתמש.

השאירו את forceLoginMethod ואת forceLoginOrgUUID מחוץ ל-payload. Claude Code עדיין קורא את שני המפתחות מה-payload לבדיקת האישורים בעלייה, כך שמפתח ששומר אישור שהונפק על ידי Anthropic במכונה מקבל את יציאת העלייה המתוארת תחת מדיניות מנהל דורשת כניסה לשער Cloud גם אחרי שהם נכנסים.

#קשור