Managed Deep Agents
Vue d'ensemble
Managed Deep Agents est un runtime hébergé API-first pour créer, exécuter et exploiter des Deep Agents dans LangSmith. Il intègre la couche opérationnelle autour du harnais open-source Deep Agents — repo d'agent versionné dans le Context Hub, threads durables, runs en streaming, arborescence de fichiers gérée, stockage des credentials MCP — de sorte que tu n'aies pas à mettre en place ton propre serveur d'agent.
Pour les déploiements auto-hébergés ou les APIs Agent Server complètes, utilise plutôt un déploiement LangSmith standard via [[langgraph-cli]].
Quand l'utiliser
Utilise ce skill quand l'utilisateur veut :
- Créer ou mettre à jour un Managed Deep Agent (
POST/PATCH /v1/deepagents/agents) - Exécuter un agent sur un thread durable et streamer le résultat
- Enregistrer ou faire tourner les credentials du serveur MCP pour les outils d'un agent
- Configurer des interrupts human-in-the-loop par outil sur un agent géré
- Décider entre Managed Deep Agents et un déploiement LangSmith auto-hébergé
Prérequis
- Une clé API LangSmith pour cet espace de travail
- Le client HTTP de ton choix (
httpxen Python,fetchnatif en JS/Node 18+)
export LANGSMITH_API_KEY="<LANGSMITH_API_KEY>"
export DEEPAGENTS_BASE_URL="https://api.smith.langchain.com/v1/deepagents"
Toutes les requêtes s'authentifient via l'en-tête X-Api-Key :
X-Api-Key: <LANGSMITH_API_KEY>
Flux de bout en bout
1. Enregistrer les serveurs MCP → POST /v1/deepagents/mcp-servers
2. Créer l'agent → POST /v1/deepagents/agents
3. Créer un thread → POST /v1/deepagents/threads
4. Streamer un run → POST /v1/deepagents/threads/{thread_id}/runs/stream
5. Inspecter dans LangSmith → IU Traces
Chaque étape est indépendante — enregistre les serveurs MCP une fois par espace de travail, puis pointe n'importe quel nombre d'agents dessus.
Groupes de ressources
| Groupe | Objectif |
|---|---|
Agents (/agents) |
Créer, lister, récupérer, mettre à jour (PATCH) et supprimer des Managed Deep Agents. |
Threads (/threads) |
Créer, rechercher, compter et inspecter l'état des threads durables. |
Runs (/threads/{thread_id}/runs/stream) |
Démarrer et streamer les runs sur un thread (server-sent events). |
Serveurs MCP (/mcp-servers) |
Enregistrer, lister, faire tourner les credentials, et supprimer les serveurs MCP référencés par les outils des agents. |
Arborescence de fichiers d'agent
Managed Deep Agents conserve la structure habituelle des projets Deep Agents. Garde-les dans ton repo source (pour que les mises à jour soient examinables) et soumets-les dans les payloads POST / PATCH /agents. La plateforme les stocke en tant que repo d'agent versionné dans le Context Hub, retourne une revision à chaque mise à jour, et sert l'arborescence à l'agent à chaque run.
| Fichier / répertoire | Objectif |
|---|---|
AGENTS.md |
Instructions de l'agent. |
skills/ |
Définitions de skills que l'agent peut utiliser. |
subagents/ |
Définitions de subagents pour le travail délégué. |
tools.json |
Configuration des outils (tools + interrupt_config). |
À l'exécution, l'agent peut lire et écrire des fichiers — y compris un répertoire /memories/ pour l'état durable entre les runs.
Configuration tools
Les outils sont configurés avec un tableau tools et une carte interrupt_config. La même structure est utilisée dans tools.json et inline dans les payloads de création/mise à jour d'agent :
{
"tools": [
{
"name": "tavily-search",
"mcp_server_url": "https://mcp.tavily.com/mcp/",
"mcp_server_name": "tavily",
"display_name": "tavily-search"
}
],
"interrupt_config": {
"https://mcp.tavily.com/mcp/::tavily-search::tavily": false
}
}
- Chaque
tools[].mcp_server_urldoit correspondre à un serveur MCP déjà enregistré pour l'espace de travail ; les credentials sont attachés automatiquement au moment de l'invocation. - Les clés
interrupt_configutilisent la forme{mcp_server_url}::{tool_name}(deux points-virgules, les barres obliques de fin sur l'URL sont supprimées avant la correspondance). Des parties supplémentaires séparées par::(par ex. le nom d'affichage du serveur MCP) sont acceptées mais ignorées lors de la correspondance. - Définis la valeur à
truepour exiger l'approbation humaine avant que l'outil ne s'exécute,falsepour l'autoriser sans interrupt.
Étape 1 — Enregistrer un serveur MCP
Les outils qui ont besoin de credentials (serveurs MCP personnalisés, endpoints privés, toute API authentifiée par bearer token) sont enregistrés une fois par espace de travail via POST /v1/deepagents/mcp-servers. La plateforme stocke l'URL et les en-têtes de credentials (chiffrés au repos) et les réattache à chaque invocation dont tools[].mcp_server_url correspond.
import os, httpx
BASE_URL = os.environ["DEEPAGENTS_BASE_URL"]
HEADERS = {"X-Api-Key": os.environ["LANGSMITH_API_KEY"]}
response = httpx.post(
f"{BASE_URL}/mcp-servers",
headers=HEADERS,
json={
"name": "tavily",
"url": "https://mcp.tavily.com/mcp/",
"headers": [
{"key": "Authorization", "value": "Bearer tvly-..."},
],
},
)
response.raise_for_status()
mcp_server_id = response.json()["id"]
Autres opérations sur la même ressource :
| Action | Méthode + chemin |
|---|---|
| Lister | GET /mcp-servers |
| Récupérer un | GET /mcp-servers/{mcp_server_id} |
| Faire tourner les credentials | PATCH /mcp-servers/{mcp_server_id} (remplace l'ensemble du tableau headers — les diffs partiels ne sont pas supportés) |
| Supprimer | DELETE /mcp-servers/{mcp_server_id} |
Seule l'authentification par en-tête statique (bearer tokens, en-têtes de clé API personnalisés) est supportée durant la preview. Les serveurs MCP utilisant OAuth sont prévus.
Étape 2 — Créer l'agent géré
response = httpx.post(
f"{BASE_URL}/agents",
headers=HEADERS,
json={
"name": "research-assistant",
"description": "Research assistant that can search the web and summarize sources.",
"runtime": {"model": {"model_id": "anthropic:claude-sonnet-4-6"}},
"instructions": (
"You are a careful research assistant. Search for sources, "
"keep notes, and return concise answers with citations."
),
"tools": {
"tools": [
{
"name": "tavily-search",
"mcp_server_url": "https://mcp.tavily.com/mcp/",
"mcp_server_name": "tavily",
"display_name": "tavily-search",
},
],
"interrupt_config": {
"https://mcp.tavily.com/mcp/::tavily-search::tavily": False,
},
},
},
)
response.raise_for_status()
agent_id = response.json()["id"]
La réponse inclut l'id de l'agent (stocke-le sous AGENT_ID).
Autres opérations :
| Action | Méthode + chemin |
|---|---|
| Lister | GET /agents |
| Récupérer un | GET /agents/{agent_id} |
| Mettre à jour | PATCH /agents/{agent_id} |
| Supprimer | DELETE /agents/{agent_id} |
PATCH remplace tools en bloc — pour ajouter un outil, passe l'ensemble complet des nouveaux outils, pas seulement les ajouts. Chaque PATCH crée aussi une nouvelle revision sur le repo du Context Hub de l'agent.
Supprimer un agent ne supprime PAS en cascade ses threads. Les threads existants restent interrogeables mais démarrer de nouveaux runs retourne 502. Suive et supprime les threads explicitement lors du nettoyage.
Modèles supportés
Passe les identifiants de modèle sous la forme {provider}:{model_id} (par ex. anthropic:claude-sonnet-4-6, openai:gpt-5.4-mini). Le runtime résout les modèles avec init_chat_model, donc tout provider supporté par init_chat_model fonctionne.
Les valeurs sans point-virgule sont interprétées comme des références à une configuration Playground sauvegardée, non comme un ID de modèle — fournis toujours la forme complète {provider}:{model_id} lors de la configuration directe d'un modèle.
Étape 3 — Créer un thread
Les threads préservent la conversation et l'état d'exécution pour les travaux de longue durée.
response = httpx.post(
f"{BASE_URL}/threads",
headers=HEADERS,
json={
"agent_id": agent_id,
"options": {
"test_run": False,
"skip_memory_write_protection": False,
},
},
)
response.raise_for_status()
thread_id = response.json()["id"]
Étape 4 — Streamer un run
payload = {
"agent_id": agent_id,
"messages": [
{
"role": "user",
"content": "Research recent approaches to agent memory and summarize the main tradeoffs.",
}
],
"stream_mode": ["values", "updates", "messages-tuple"],
"stream_subgraphs": True,
"user_timezone": "America/Los_Angeles",
}
with httpx.stream(
"POST",
f"{BASE_URL}/threads/{thread_id}/runs/stream",
headers={**HEADERS, "Accept": "text/event-stream"},
json=payload,
timeout=None,
) as response:
response.raise_for_status()
for line in response.iter_lines():
if line:
print(line)
Définis Accept: text/event-stream pour que le client reçoive la progression sous forme SSE. stream_mode accepte les mêmes valeurs que le runtime LangGraph (values, updates, messages-tuple, etc.). stream_subgraphs: true émet les événements des graphes de subagents ainsi que du parent.
Chaque run est tracé dans LangSmith — les appels de modèle, les appels d'outils, l'activité des subagents, les fichiers et l'état du runtime sont tous inspectables depuis l'IU de traçage.
Équivalents JavaScript / cURL
Le même flux fonctionne avec fetch (Node 18+ ou navigateur) ou curl. Remplace httpx.post(url, headers=HEADERS, json=...) par :
const BASE_URL = process.env.DEEPAGENTS_BASE_URL;
const HEADERS = {
"X-Api-Key": process.env.LANGSMITH_API_KEY,
"Content-Type": "application/json",
};
const response = await fetch(`${BASE_URL}/agents`, {
method: "POST",
headers: HEADERS,
body: JSON.stringify({ /* même payload */ }),
});
if (!response.ok) throw new Error(await response.text());
const { id: agentId } = await response.json();
Pour le streaming, lis depuis response.body.pipeThrough(new TextDecoderStream()).getReader().
Pour curl, définis --header "X-Api-Key: $LANGSMITH_API_KEY" et --header 'Content-Type: application/json'.
Quand NE PAS utiliser Managed Deep Agents
Utilise plutôt un déploiement LangSmith standard via [[langgraph-cli]] (langgraph deploy) quand tu as besoin de :
- Code d'application personnalisé ou routes personnalisées autour de l'agent
- Authentification avancée
- Toute la surface de l'API Agent Server
- Contrôles d'isolation plus forts ou scalabilité maximale
- Une région autre que US LangSmith Cloud, ou auto-hébergée/Hybrid
Pièges à éviter
- Pas de SDK — REST est la seule interface supportée. Des wrappers SDK Python/JS/
useStreamsont en cours. - Pas de limites de taux durant la preview — mais des quotas peuvent être introduits avant GA ; ne conçois pas en supposant l'absence de limites.
PATCHest en bloc, pas partiel — à la fois pour lesagents(le champtoolsest remplacé) et pour lesmcp-servers(le tableauheadersest remplacé). Envoie toujours la nouvelle valeur complète.- Format de clé
interrupt_config—{mcp_server_url}::{tool_name}avec deux points-virgules. Les barres obliques de fin sur l'URL sont supprimées avant la correspondance. - Les IDs de modèle doivent inclure le préfixe du provider —
anthropic:claude-sonnet-4-6, pasclaude-sonnet-4-6(ce dernier est traité comme une référence de configuration Playground). - Les credentials MCP sont sensibles —
headersest omis des corps de réponse pour les appelants sans permission d'invocation ; traite les réponses list/get comme sensibles et évite de les enregistrer textuellement. - L'authentification MCP limitée aux en-têtes statiques — bearer tokens et en-têtes de clé API personnalisés seulement durant la preview. L'enregistrement utilisant OAuth est prévu.
- Supprimer un agent ne supprime pas ses threads — et les nouveaux runs sur les threads orphelins retournent
502. Nettoie les threads explicitement. - Stabilité de l'API — les routes vivent sous
/v1/deepagentsmais la surface peut changer de manière rétro-incompatible avant GA. Les changements cassants sont communiqués directement aux clients de la preview.