LangGraph
guardian_agent.langgraph: describe_graph, which describes a hand-built LangGraph graph as an agent that signs its own requests.
Hand-built LangGraph graphs, as agents that sign their own requests.
Give describe_graph the function that builds your graph and the chat
models it uses. It calls that function once, with each model routed through
the proxy as the agent, describes the graph it built, and returns it:
from guardian_agent.langgraph import describe_graph
def build(llm):
graph = StateGraph(MessagesState)
... # your nodes call llm
return graph.compile()
app = describe_graph(build, name="inventory", models={"llm": ChatOpenAI(...)})Needs langgraph, which the langchain extra brings.
Functions:
- describe_graph – Your LangGraph graph, built with routed models, described, as the agent
name.
langgraph.describe_graph
describe_graph(build: Callable[..., Any], *, name: str, models: Mapping[str, BaseChatModel | str], tools: Sequence[BaseTool | Callable[..., Any] | dict[str, Any]] = (), instructions: Instruction | Sequence[Instruction] | None = None, description: str | None = None, version: str | None = None, sources: Iterable[Source] = (), exclude: Sequence[str] = (), guardian: Guardian | None = None) -> CompiledStateGraph[Any, Any, Any, Any]Your LangGraph graph, built with routed models, described, as the agent name.
build is called once, with each of models routed through the proxy
as the agent and passed by name, so every call its nodes make is signed
as the agent. The definition records the models, the graph’s nodes and
edges (a subgraph’s too, named outer:inner), each node’s and router’s
code with the values it captured, and the tools of each ToolNode.
Each request is checked as it’s built: one sending settings, or offering
a tool, the definition doesn’t describe is refused before it’s sent.
Example:
def build(llm: ChatOpenAI):
model = llm.bind_tools([inventory])
def answer(state: MessagesState):
return {"messages": [model.invoke(state["messages"])]}
graph = StateGraph(MessagesState)
graph.add_node("answer", answer)
graph.add_edge(START, "answer")
return graph.compile()
app = describe_graph(
build, name="inventory", models={"llm": ChatOpenAI(model="gpt-4.1")}
)Parameters:
- build (
Callable[..., Any]) – Builds your graph from the routed models, given by name, and returns it compiled, or as aStateGraphto compile as it is. - name (
str) – The agent’s name, as enrolled withviper agent add. - models (
Mapping[str, BaseChatModel | str]) – Each ofbuild’s parameters that takes a chat model, and the model: a chat model, or a"provider:model"name built withinit_chat_model(ascreate_agenttakes one); in the definition in this order. - tools (
Sequence[BaseTool | Callable[..., Any] | dict[str, Any]]) – Tools the graph’s models are offered besides those in itsToolNodes. - instructions (
Instruction | Sequence[Instruction] | None) – Text for a system prompt, or a list of prompts, asguardian_agent.Definitiontakes them. - description (
str | None) – What the agent is for. - version (
str | None) – Your own label for this version of the agent. - sources (
Iterable[Source]) – Source files to fingerprint, such as a module whose constants your nodes read. - exclude (
Sequence[str]) – JSON Pointers to fields to leave out of the definition, such as/extensions/langgraph/nodes/answerfor a node holding a value that can’t be recorded. - guardian (
Guardian | None) – The proxy to use;Guardian()(VIPER_PROXY_URL) by default.
Returns:
CompiledStateGraph[Any, Any, Any, Any]– The compiled graph, whose models are routed as the agent.agent_of(graph)is the SDK’s agent.
Raises:
TypeError–modelsis empty, names a parameterbuilddoesn’t take, or holds somethingbind()can’t route;buildreturned something other than a LangGraph graph; or a node or router holds a chat model that isn’t one of the routed models.ValueError– A router’s destinations can’t be seen (give it aLiteralreturn type or apath_map); a node holds a value that can’t be recorded; or a model sends a setting no definition can record.DefinitionInvalid– The definition breaks a rule.DefinitionContainsSecret– It holds what looks like a credential.