Managed Deep Agents is in public beta and available on LangSmith Cloud in the US region only.
Understand the runtime types
Managed Deep Agents extends one native type for each place your code runs:
Type parameters follow the native order, so
ManagedToolRuntime takes state first, then context. Both parameters are optional. ManagedDeepAgentRuntime is an alias for ManagedToolRuntime.
Each type keeps every native field and method, such as context, state, store, writer, and toolCallId. Managed Deep Agents adds three fields:
serverInfo: Native server metadata plus the verified caller. Tools and middleware receive it.channel: The verified channel delivery that started the run.undefinedon direct API and schedule runs.backend: The thread’s sandbox filesystem.undefinedwhen the project declares no sandbox.
Separate context, caller, and delivery
Context, the caller, and the channel delivery come from different sources and have different trust levels. The runtime keeps them in separate fields:- Context comes from the
contextparameter of an API call. LangGraph validates it against your context schema. Use it to select behavior, not to grant access. - Server info comes from identity, which resolves the caller from a verified token. Managed Deep Agents strips identity keys that a client sends through
configurable, so use this field for authorization. - Channel comes from managed channel ingress, which verifies the delivery before the run starts. A
channelkey in a direct API call’s context does not createruntime.channel.
Handle channel runs without context
A channel delivery carries no application context. Managed Deep Agents removes delivery data before LangGraph validates context, so required context fields do not reject channel runs. Direct API runs keep native validation. On channel runs, context isundefined in the agent factory and tools, and an empty object in native middleware.
To tell a channel run from a direct run, check runtime.channel.
Read the runtime in the agent factory
An agent factory receives aManagedServerRuntime: the native ServerRuntime plus channel and backend. To write a factory, see Select configuration per run.
Agent Server also calls the factory to read schemas and state. accessContext names the operation. executionRuntime is null outside threads.create_run, so read run context from executionRuntime.context. Return the same graph structure and schemas from every call.
channel is available, so a factory can choose configuration per channel. backend is always undefined, because the factory selects the sandbox.
Read the runtime in tools
Annotate the runtime parameter withManagedToolRuntime:
tools/check-order.ts
principal is absent when no caller resolved, because identity is opt-in. post sends an additional message, and the agent’s final reply still posts automatically. For more on writing tools, see Custom tools.
Read the runtime in middleware
Cast the hook’s runtime toManagedRuntime to read the managed fields:
middleware/log-caller.ts
ManagedToolRuntime. Declarative subagents receive the same managed fields. Neither requires an identity or sandbox declaration. For more on writing middleware, see Custom middleware.
Reference the managed fields
Server info
runtime.serverInfo is a ManagedServerInfo. It keeps the native assistantId, graphId, and user fields and adds the caller:
principal: The verified caller.idis the caller ID,kindis"person","service", or"channel", andclaimsholds the token claims.claims.groupsis always a string array, andclaims.emailis always a string.subject: The authority the run acts with.authorityis"agent"or"user", withagent_idanduser_id.link: The account link.statuscurrently reports"not_required".source: Where the run entered.provideris a value such as"http","schedule","studio", or"slack", with an optionalthreadId.
principal, not from the native user. For identity providers and claim mapping, see Identity.
Channel
runtime.channel is a RuntimeChannel:
name: The configured channel name.provider: The provider label, such as"slack".event: The typed delivery. See the event types below.rawEvent: The original provider payload, when the channel supplies one. For Slack, this is the inner Slack event without HTTP headers or the Trigger envelope. A resume can omit it.post: An async function that sends a message to the conversation that started the run.undefinedwhen the channel cannot send.
event.type is one of:
message: A new message.messagesholds the incoming messages.user_prompt_response: A reply to an interactive prompt. Carriesaction, an optionalvalue, and an optionalcorrelation_id. See Agent-owned interrupts.interrupt_resume: A resume for a pending interrupt.resumeholds the resume value.
post accepts a content message, {"type": "content", "content": ...}, or a native message, {"type": "native", "native": ...}. The built-in Slack channel sends text content only. The reply target stays private: post has no address or destination override, and code cannot read or replace the target.
Backend
runtime.backend reads and writes files in the thread’s sandbox. See Read and write sandbox files from code.
See also
Connect these docs to your agent of choice via MCP for real-time answers.

