Aller au contenu principal

Restrictions de domaine des Managed Agents

Avancé
What you'll learn
  • Comprendre quelles menaces une liste d'autorisation/de blocage de domaines par outil arrête réellement dans les Managed Agents — et lesquelles elle n'arrête pas
  • Épingler web_search et web_fetch à des hôtes précis via le tableau configs de agent_toolset_20260401
  • Lire les dix règles de format de domaine qu'Anthropic valide à la création, pour qu'un 400 n'expédie pas votre bug en production
  • Raisonner sur la sémantique multiagent — pourquoi les listes d'autorisation s'intersectent et les listes de blocage s'additionnent entre le coordinateur et le roster
  • Gérer le tool_result url_not_allowed et les événements session.error à l'exécution, et savoir quand la revalidation a lieu
  • Distinguer ces réglages du filtre de domaines des server tools de la Messages API et de la politique réseau du bac à sable

Une session Managed Agents autonome qui embarque web_search et web_fetch est un forgeur de requêtes doté d'un moteur de recherche. Toute chaîne qu'on peut l'amener à croire être une « URL de référence utile » — une charge d'injection de prompt dans une page récupérée, un lien dans un magasin de mémoire, une pure hallucination du modèle — devient une requête sortante que le crawler d'Anthropic effectuera en votre nom. Jusqu'à cette bêta, le seul moyen d'empêcher cela était de désactiver les outils et de les réintroduire comme outils personnalisés que vous validiez vous-même.

La bêta du 26 août ajoute des listes allowed_domains et blocked_domains de première classe par outil — plus max_content_tokens sur les fetches et user_location sur les recherches — appliquées sur les serveurs d'Anthropic avant que la requête sortante ne soit effectuée. Deux points de cette formulation importent :

  • L'application se fait sur les serveurs d'Anthropic, pas dans votre bac à sable. La politique networking du bac à sable (qui contrôle ce que le code à l'intérieur du bac à sable peut atteindre) est donc sans rapport. Si vous laissez le toolset sans listes de domaines tout en verrouillant le réseau du bac à sable, le web_fetch de l'agent atteint quand même ce qu'il veut — le fetch s'exécute en dehors du bac à sable.
  • Les filtres web au niveau de l'organisation dans la Claude Console ne s'appliquent qu'à la Messages API. Ils ne se rattachent pas aux sessions Managed Agents. Si votre organisation a une règle « bloquer ads.example.com » au niveau console et que vous ne la répliquez jamais dans le toolset, une session d'agent la récupérera.

Où vit le réglage​

Chaque outil intégré se trouve dans l'objet toolset agent_toolset_20260401 du tableau tools de l'agent, et chaque outil est configuré via une entrée du tableau configs de ce toolset. Les entrées sont identifiées par name (web_search, web_fetch, bash, read, write, edit, glob, grep), typées par un champ type optionnel portant la même valeur, et — pour les deux outils web — acceptent allowed_domains, blocked_domains, max_content_tokens et user_location aux côtés des habituels enabled et permission_policy.

La forme minimale :

Épingler web_search et web_fetch à deux hôtes, plafonner le contenu récupéré

{
"type": "agent_toolset_20260401",
"configs": [
  {
    "name": "web_search",
    "allowed_domains": ["docs.example.com", "arxiv.org"],
    "user_location": {
      "type": "approximate",
      "country": "US",
      "timezone": "America/Los_Angeles"
    }
  },
  {
    "name": "web_fetch",
    "blocked_domains": ["ads.example.com"],
    "max_content_tokens": 50000
  }
]
}

Chaque outil porte sa propre liste — une liste d'autorisation de recherche ne contraint pas les fetches et réciproquement. Si vous voulez que les deux listes évoluent ensemble, répliquez-les vous-même.

Une création d'agent complète​

POST /v1/agents — la requête entière

curl -fsSL https://api.anthropic.com/v1/agents \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: managed-agents-2026-04-01" \
-H "content-type: application/json" \
-d '{
  "name": "Research Agent",
  "model": "claude-opus-5",
  "tools": [
    {
      "type": "agent_toolset_20260401",
      "configs": [
        {
          "name": "web_search",
          "allowed_domains": ["docs.example.com", "arxiv.org"],
          "user_location": {
            "type": "approximate",
            "country": "US",
            "timezone": "America/Los_Angeles"
          }
        },
        {
          "name": "web_fetch",
          "blocked_domains": ["ads.example.com"],
          "max_content_tokens": 50000
        }
      ]
    }
  ]
}'

Dans les SDK Python, TypeScript, Go, Java, C#, Ruby et PHP, chaque entrée de configs est typée par outil comme une union discriminée (BetaManagedAgentsWebSearchToolConfigParams, BetaManagedAgentsWebFetchToolConfigParams, etc.). type est optionnel à la construction parce que le serveur le déduit de name, mais il revient toujours dans les réponses. Les requêtes qui ne définissent que name, enabled et permission_policy restent valides avec ou sans type — l'ancien code n'a pas besoin d'être réécrit pour accueillir cette bêta.

Les dix règles de format de domaine​

Anthropic valide chaque domaine listé au moment de la création/mise à jour de l'agent et de la création/mise à jour de la session, et renvoie un 400 invalid_request_error avec un message qui nomme la liste et la position en base zéro de l'entrée fautive (allowed_domains.0: IP addresses are not supported…). Les règles sont plus strictes que ce qu'accepte la Messages API, et chacune est un piège dans la nature :

Guided walkthrough1 of 10
  1. Définissez soit allowed_domains, soit blocked_domains sur une entrée — jamais les deux. Une entrée portant les deux est rejetée : "Only one of allowed_domains or blocked_domains may be set."

Deux vérifications supplémentaires dépendent des fournisseurs sous-jacents et sont elles aussi appliquées à la création/mise à jour : un domaine auquel le crawler d'Anthropic ne peut pas accéder est refusé pour allowed_domains, un user_location.country non pris en charge renvoie un message se terminant par user_location.country: not a country the search provider supports, et un user_location.timezone doit être un nom IANA valide.

Sessions multiagent — comment les listes se combinent​

Une session multiagent peut superposer trois ensembles de listes sur un même appel d'outil : les listes actuelles du coordinateur, les listes de tout agent qui a appelé celui-ci, et les listes propres à l'agent du roster. Chaque liste applicable au thread est appliquée en même temps.

  • Les listes d'autorisation s'intersectent. L'ensemble effectif est celui des domaines couverts par toutes les listes d'autorisation applicables. Un agent du roster peut restreindre ce qu'un outil atteint, jamais l'élargir — définissez sur un agent du roster une liste d'autorisation qui n'est pas incluse dans celle du coordinateur et chaque appel reviendra avec une erreur url_not_allowed dont le message indique qu'aucun domaine n'est permis. La description de l'outil le dit au modèle d'emblée.
  • Les listes de blocage s'additionnent. Chaque liste de blocage applicable est appliquée conjointement, donc tout hôte figurant sur la liste de blocage de n'importe quel niveau est injoignable pour ce thread.
  • max_content_tokens et user_location ne se combinent pas. Un thread lit d'abord sa propre configuration d'outil, puis celle de l'agent appelant, puis la configuration actuelle du coordinateur — la première valeur non nulle l'emporte.
  • Les entrées de roster {"type": "self"} n'ont pas de réglages web propres et suivent la configuration actuelle du coordinateur.
  • Le grader des sessions orientées résultats s'exécute sans aucun outil web — aucune liste d'autorisation ou de blocage n'a d'importance, puisque le grader n'a ni web_search ni web_fetch à exécuter.

La conséquence : si la liste d'autorisation du coordinateur est [docs.example.com, arxiv.org] et celle d'un agent du roster est [github.com], l'agent du roster n'a aucun hôte joignable. Concevez les listes d'autorisation des agents du roster comme des sous-ensembles de celle du coordinateur, ou ne les définissez pas du tout.

Mises à jour en cours de session et la seconde validation​

Vous pouvez mettre à jour les outils d'une session inactive pour changer les listes de domaines — les nouvelles listes s'appliquent à partir de ce moment. Dans une session multiagent, chaque thread récupère les nouvelles listes à son tour suivant, mais les listes propres à un agent du roster sont figées au moment de la création de la session (elles vivent sur la définition de l'agent, pas sur la session).

Une seconde validation a lieu quand la session initialise l'outil pour la première fois. Un domaine qui a passé la vérification synchrone à la création peut encore échouer plus tard (un hôte autorisé peut avoir perdu l'accès du crawler dans l'intervalle). Si la vérification à l'exécution échoue, la session émet un événement session.error, revient à idle et ne réessaie pas. Le correctif consiste à mettre à jour les outils de la session, à mettre à jour l'agent aussi pour que les nouvelles sessions démarrent proprement, puis à envoyer un nouveau user.message.

Le chemin d'erreur à l'exécution​

Au moment de la session, les deux outils se comportent différemment lorsqu'ils rencontrent une URL que leurs listes interdisent.

  • web_fetch renvoie un résultat d'erreur à l'agent : is_error: true sur l'événement agent.tool_result, avec un bloc de contenu qui nomme le code d'erreur url_not_allowed. Le modèle le voit et peut s'adapter (choisir une autre source, demander à l'utilisateur, ou s'arrêter) — c'est un échec d'outil normal, pas un échec de session.
  • web_search omet silencieusement tout résultat dont l'hôte n'est pas permis par les listes. Le modèle ne les voit pas du tout. C'est le bon comportement par défaut pour une recherche — l'alternative ferait fuiter dans la transcription les URL des résultats filtrés — mais cela veut dire qu'une recherche qui ne renvoie « aucun résultat » pour ce qui devrait être une bonne requête est un signal pour élargir la liste d'autorisation, pas seulement pour réessayer.

Les deux signaux ont leur place dans votre gestionnaire d'événements de session. session.error pour le raté au moment de l'initialisation, agent.tool_result avec is_error: true et url_not_allowed pour le raté par appel, et — en tant que signal de taux — tout tour de recherche dont le nombre de résultats tombe à zéro alors que la liste d'autorisation est petite.

Différences avec le filtre de domaines des server tools de la Messages API​

Les Managed Agents appliquent délibérément un régime plus strict que les filtres web_search et web_fetch des server_tools de la Messages API. Le vocabulaire est le même, mais quatre choses sont plus serrées et une chose manque carrément :

  • Le plafond de liste est de 64 domaines, contre un plafond plus élevé pour la Messages API. Les grosses listes d'autorisation ne se transposent pas — découpez-les entre plusieurs agents.
  • Les domaines web_fetch ne peuvent pas inclure de chemin. La Messages API accepte les chemins sur les deux outils. Convertissez en noms d'hôtes simples toutes les entrées du style Messages API example.com/blog lors du portage.
  • ASCII uniquement — Punycode requis pour les noms internationalisés. La Messages API autorise les entrées Unicode (tout en les déconseillant).
  • max_uses, citations et cache_control ne sont pas disponibles sur le toolset. Ce sont des réglages réservés à la Messages API que le toolset a choisi de ne pas exposer. Concevez plutôt autour de la tarification par session et du paramètre response_inclusion.

Si vous portez un agent Messages API existant vers les Managed Agents, la plupart des filtres existants se transfèrent proprement. Les entrées nues du type example.com, la correspondance incluant les sous-domaines et la règle « une seule liste par entrée » sont toutes identiques.

Pièges courants — cinq qui font tomber de vraies équipes​

  1. www.example.com n'est pas example.com. Ne lister que www.example.com n'autorisera pas l'apex nu example.com, et ne lister que example.com couvrira quand même www.example.com (parce que www. est un sous-domaine comme un autre). Listez le domaine nu pour avoir les deux.
  2. La politique networking du bac à sable n'affecte pas ces outils. web_search et web_fetch tournent sur les serveurs d'Anthropic : un environnement qui refuse toute sortie depuis le bac à sable récupère donc allègrement tout ce que le toolset autorise. Si vous voulez de la défense en profondeur, répliquez les deux politiques.
  3. Les filtres d'organisation au niveau console ne se rattachent pas. Les filtres web à l'échelle de l'organisation dans la Console concernent uniquement la Messages API. Une règle « bloquer ads.example.com » définie dans la Console ne touche jamais les Managed Agents.
  4. Ajouter un budget de session n'implique pas une restriction de domaine. Les budgets de session plafonnent des dollars, pas des destinations. Une session budgétée peut brûler son plafond à récupérer une seule page hostile. Utilisez les deux.
  5. Un suffixe de chemin sur web_search est un motif d'URL, pas une règle d'hôte. Préférez les noms d'hôtes simples — les filtres de chemin sur la recherche n'ont qu'une valeur indicative et le fournisseur peut les faire correspondre plus largement que vous ne l'attendez.

Ce que cela atténue réellement​

Soyez précis sur le modèle de menace — surestimer la portée ici mord les équipes qui supposent que c'est un correctif SSRF complet. Ce n'en est pas un. Les trois risques concrets qu'il couvre :

  • La navigation par injection de prompt. Une page empoisonnée ou une entrée de magasin de mémoire qui ordonne à l'agent de « récupérer cette URL pour continuer » échoue avec url_not_allowed si l'hôte n'est pas autorisé, et le modèle voit l'erreur et (généralement) s'arrête.
  • Les destinations publicitaires et de télémétrie. Une liste de blocage tient les fetches de l'agent à l'écart des domaines de pistage vers lesquels une page cible essaie de le faire rebondir.
  • L'exfiltration de données via fetch. Un agent amené à construire une URL web_fetch avec des paramètres de requête sensibles (?leaked=<memory>) ne peut pas atteindre un récepteur hostile dont l'hôte n'est pas autorisé.

Ce qu'il n'arrête pas : les requêtes sortantes des outils personnalisés que vous définissez, des outils de serveurs MCP, du code que votre bac à sable exécute, ou de tout outil qui n'est ni web_search ni web_fetch. Chacun de ceux-là a son propre réglage (networking du bac à sable, listes d'autorisation des serveurs MCP, code des outils personnalisés). Ce réglage unique n'est qu'une couche dans une histoire à plusieurs couches.

Key takeaways
  • allowed_domains et blocked_domains vivent par outil dans le tableau configs de agent_toolset_20260401 ; chaque outil porte sa propre liste et elles n'évoluent pas ensemble automatiquement
  • Dix règles de format — pas de schéma, pas de port, pas de joker, pas de chemin sur web_fetch, pas de TLD nu, pas de localhost ni de .local, Punycode pour les IDN, de 1 à 64 domaines, pas de doublons, la correspondance de sous-domaine ne va que vers le bas
  • Sémantique multiagent : les listes d'autorisation s'intersectent et les listes de blocage s'additionnent. Un agent du roster peut restreindre mais jamais élargir la portée du coordinateur
  • À l'exécution : web_fetch échoue sur une URL interdite avec is_error et url_not_allowed ; web_search omet silencieusement les résultats interdits
  • C'est réservé aux Managed Agents. Les filtres d'organisation de la Console ne se rattachent pas, et la politique réseau du bac à sable n'affecte pas ces outils — répliquez les règles si vous voulez de la défense en profondeur
  • Ce n'est pas la même chose que le filtre des server tools de la Messages API : plus strict (plafond de 64, pas de chemins sur web_fetch, ASCII uniquement) et il manque max_uses, citations, cache_control

Vérifiez vos acquis​

Vérifiez vos acquis

0/5
  1. Vous définissez allowed_domains: ["example.com"] sur l'entrée web_fetch. Lesquelles de ces URL l'agent sera-t-il autorisé à récupérer ?
  2. La liste d'autorisation web_fetch d'un coordinateur est ["docs.example.com", "arxiv.org"]. Un agent du roster définit sa propre liste d'autorisation web_fetch à ["github.com"]. Que se passe-t-il quand l'agent du roster tente de récupérer https://github.com/anthropic-ai/sdk ?
  3. Votre équipe a pour politique de bloquer ads.example.com au niveau de l'organisation dans la Claude Console. Vous lancez une session Managed Agents avec web_fetch activé et aucune liste de domaines. L'agent récupère https://ads.example.com. Que se passe-t-il ?
  4. Vous soumettez un agent avec allowed_domains: ["https://docs.example.com", "127.0.0.1", "co.uk"]. Que renvoie l'API ?
  5. Un appel web_fetch vers une URL que sa liste n'autorise pas fait quoi ?

Sources et lectures complémentaires​

Pour aller plus loin​