Govern agents built with ADK, Agent Framework, LangChain, CrewAI and the OpenAI Agents SDK
AI agents built in any framework reach your tools and your models through Quilzo, and only as your declarations allow.
In the adminIntegrations
Every major agent framework speaks MCP. Point its MCP client at Quilzo's governed gateway instead of at your tool server, and the agent gets only the tools a person pinned, at the role and daily limit you set, with Quilzo's credential injected, calls you chose held for a person, and every call recorded in the signed log. Their models can go through Quilzo too: point the framework's model client at Quilzo's model gateway, and each call is budgeted, masked and recorded, with the agent's memory. Nothing changes in the agent's code except the address and a token.
Offer a tool server through the gateway
Declare the server, pin the tools you agreed to, and offer it (see Tools and the MCP gateway for every field):
quilzo integrations tools tracker
quilzo integrations pin tracker list_issues create_issue
quilzo integrations gateway tracker --role author --daily 200 --ask create_issue
quilzo token issue support-agent --principal dana --role author
The agent then connects to https://YOUR-ADMIN/mcp/gateway/tracker with the token as a bearer credential, or through OAuth 2.1 (see Connect AI apps). The token acts for the person it was issued to, with their access and no more. Each example below reads it from QUILZO_TOKEN.
The same clients reach Quilzo's own operations at /mcp, or over stdio with quilzo mcp.
Google ADK
pip install "google-adk[mcp]"
import os
from google.adk.agents import Agent
from google.adk.tools.mcp_tool import McpToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams
root_agent = Agent(
model="gemini-flash-latest",
name="support_agent",
instruction="Help the support team find and file issues in the tracker.",
tools=[
McpToolset(
connection_params=StreamableHTTPConnectionParams(
url="https://quilzo.example.com/mcp/gateway/tracker",
headers={"Authorization": "Bearer " + os.environ["QUILZO_TOKEN"]},
),
)
],
)
Microsoft Agent Framework
pip install agent-framework
import asyncio
import os
from agent_framework import Agent, MCPStreamableHTTPTool
from agent_framework.openai import OpenAIChatClient
async def main():
async with MCPStreamableHTTPTool(
name="tracker",
url="https://quilzo.example.com/mcp/gateway/tracker",
static_headers={"Authorization": "Bearer " + os.environ["QUILZO_TOKEN"]},
) as tracker:
agent = Agent(
client=OpenAIChatClient(model="gpt-5"),
instructions="Help the support team find and file issues in the tracker.",
tools=tracker,
)
print(await agent.run("Is the checkout timeout already reported?"))
asyncio.run(main())
The header is passed as static_headers.
LangChain and LangGraph
pip install langchain langchain-mcp-adapters langchain-openai
import asyncio
import os
from langchain.agents import create_agent
from langchain_mcp_adapters.client import MultiServerMCPClient
async def main():
client = MultiServerMCPClient({
"tracker": {
"transport": "streamable_http",
"url": "https://quilzo.example.com/mcp/gateway/tracker",
"headers": {"Authorization": "Bearer " + os.environ["QUILZO_TOKEN"]},
}
})
tools = await client.get_tools()
agent = create_agent("openai:gpt-5", tools)
print(await agent.ainvoke({"messages": "Is the checkout timeout already reported?"}))
asyncio.run(main())
CrewAI
pip install crewai "crewai-tools[mcp]"
import os
from crewai import Agent, Crew, Task
from crewai_tools import MCPServerAdapter
tracker = {
"url": "https://quilzo.example.com/mcp/gateway/tracker",
"transport": "streamable-http",
"headers": {"Authorization": "Bearer " + os.environ["QUILZO_TOKEN"]},
}
with MCPServerAdapter(tracker) as tools:
agent = Agent(
role="Support agent",
goal="Find and file issues in the tracker",
backstory="You keep the support tracker accurate.",
tools=tools,
)
task = Task(description="Is the checkout timeout already reported?", expected_output="Yes or no, with the issue", agent=agent)
print(Crew(agents=[agent], tasks=[task]).kickoff())
OpenAI Agents SDK
pip install openai-agents
import asyncio
import os
from agents import Agent, Runner
from agents.mcp import MCPServerStreamableHttp
async def main():
async with MCPServerStreamableHttp(
name="tracker",
params={
"url": "https://quilzo.example.com/mcp/gateway/tracker",
"headers": {"Authorization": "Bearer " + os.environ["QUILZO_TOKEN"]},
},
) as tracker:
agent = Agent(
name="Support agent",
instructions="Help the support team find and file issues in the tracker.",
mcp_servers=[tracker],
)
result = await Runner.run(agent, "Is the checkout timeout already reported?")
print(result.final_output)
asyncio.run(main())
Their models, through the gateway
Once an administrator turns on models.remote, each framework's model client takes Quilzo's address and a Quilzo token as its key (see Agents built anywhere). The model is quilzo, or agent/NAME to bring that agent's memory. The tools above work alongside: a framework calls its own tools as before.
| Framework | Its model, on Quilzo |
|---|---|
| Google ADK | LiteLlm(model="openai/agent/concierge", api_base="https://quilzo.example.com/v1", api_key=token), with pip install litellm |
| Microsoft Agent Framework | OpenAIChatCompletionClient("agent/concierge", base_url="https://quilzo.example.com/v1", api_key=token), or AnthropicClient(model="agent/concierge", base_url="https://quilzo.example.com", api_key=token) |
| LangChain and LangGraph | ChatOpenAI(model="agent/concierge", base_url="https://quilzo.example.com/v1", api_key=token) |
| CrewAI | LLM(model="openai/agent/concierge", base_url="https://quilzo.example.com/v1", api_key=token) |
| OpenAI Agents SDK | OpenAIResponsesModel(model="agent/concierge", openai_client=AsyncOpenAI(base_url="https://quilzo.example.com/v1", api_key=token)) |
| Anthropic's SDK | Anthropic(base_url="https://quilzo.example.com", api_key=token) |
Agent Framework's OpenAIChatClient continues conversations it expects the provider to keep, and nothing here keeps conversations, so it is refused with that reason. Use its chat completions or Anthropic client instead.
For example, an agent built with the OpenAI Agents SDK, with a tool of its own and the memory of the concierge agent:
import asyncio
import os
from agents import Agent, OpenAIResponsesModel, Runner, function_tool
from openai import AsyncOpenAI
@function_tool
def get_weather(city: str) -> str:
"""The weather for a city."""
return "18C and clear in " + city
async def main():
quilzo = AsyncOpenAI(base_url="https://quilzo.example.com/v1", api_key=os.environ["QUILZO_TOKEN"])
agent = Agent(
name="Concierge",
instructions="Help the person you work for.",
tools=[get_weather],
model=OpenAIResponsesModel(model="agent/concierge", openai_client=quilzo),
)
result = await Runner.run(agent, "What is the weather where my team meets on Thursday?")
print(result.final_output)
asyncio.run(main())
When a call waits for a person
A call to a tool offered with --ask does not run. The framework receives an MCP error naming the held call, which a model reads as any other tool error:
a person approves each call of create_issue on tracker. This one is held as gq_a807fa3c488d: call again with the same arguments once they have decided
Somebody other than the person the call acts for decides it under Approvals or with quilzo integrations approve gq_a807fa3c488d. Approved, the same call with the same arguments goes through once, within the hour.
Agents that speak A2A
A framework with an A2A client can send work to your Quilzo agents instead of calling tools. Each task runs as one of your agents, under its declaration narrowed by the sender's token (see A2A):
curl https://YOUR-ADMIN/a2a \
-H "Authorization: Bearer $QUILZO_TOKEN" -H "A2A-Version: 1.0" -H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "SendMessage", "params": {"message": {"messageId": "m1",
"role": "ROLE_USER", "parts": [{"text": "Which page explains returns?"}], "metadata": {"agent": "helper"}}}}'
openJiuwen agent-studio
agent-studio connects to MCP services as plugins. Add the gateway's address as an MCP service with an Authorization: Bearer header carrying a Quilzo token, and the workflows and agents built there reach the tool server only through Quilzo. Its headers are the same for every session today, so every call acts for the one person the token was issued to; give that token only the role the workflows need.
NVIDIA OpenShell
Quilzo runs an agent's own program in OpenShell as one of its two sandbox backends, with the declaration compiled to OpenShell's policy and the same services handed in: the agent interface for the run, a model endpoint through Quilzo's gateway, and a proxy to the declared hosts. See Programs in a box.
Tested with
Each example above was run against Quilzo's gateway in front of an MCP server, listing its pinned tools and calling one: google-adk 2.12.0, agent-framework 1.21.0, langchain-mcp-adapters 0.3.2 with langchain 1, crewai and crewai-tools 1.15.27, and openai-agents 0.23.1.