How to pass custom HTTP headers (e.g. Authorization) from /run request into ADK tools? #4130
Replies: 2 comments
-
|
Response from ADK Answering Agent (experimental, answer may be inaccurate) TLDR: The recommended approach is to wrap the ADK runner in your own custom FastAPI server. This allows you to intercept the incoming request, extract the Hi @DonaldJacamoTP, thank you for the detailed question. This is a great use case for ADK's flexibility. Here is a guide on the recommended architecture to achieve what you're looking for, which directly answers your questions. 1. Is there an official way to pass context?Yes. The official and intended way to pass request-scoped data to your tools is through the session state. You can think of the state as a request-scoped dictionary that is accessible throughout the agent's lifecycle. Tools access this state via the from google.adk.tools import ToolContext
def my_api_tool(param: str, tool_context: ToolContext):
# Retrieve the token from the session state
auth_token = tool_context.state.get("user_auth_token")
headers = {"Authorization": f"Bearer {auth_token}"}
# ... make authenticated API callYou can find more information in the documentation on Custom Tools [1] and Context [2]. 2. Is wrapping ADK in a custom server the recommended approach?Yes, absolutely. For use cases like multi-tenancy, custom authentication, or any pre-processing of requests, wrapping ADK's core runner in your own web server is the recommended pattern. By creating your own FastAPI app, you gain full control over the request/response lifecycle. 3. What are the best practices for propagating context?Here is the best-practice workflow: Step 1: Create a Custom FastAPI Server Instead of using Step 2: Intercept the Header and Inject into State In your custom endpoint, you can access the from fastapi import FastAPI, Request
from google.adk.runtime import runner, get_session_manager
app = FastAPI()
@app.post("/run")
async def run_chat(request: Request, run_input: dict):
# 1. Extract token from the header
auth_header = request.headers.get("Authorization")
token = auth_header.split(" ")[1] if auth_header else None
# 2. Get the session and inject the token into its state
session_manager = get_session_manager()
session = await session_manager.load_session(run_input.get("sessionId"))
session.state["user_auth_token"] = token
# 3. Run the agent with the modified context
response = await runner.run_async(
app_name=run_input.get("appName"),
context=session.model_dump(),
# ... other params
)
return response(This is a simplified example. See a more complete one in the Streaming Guide [4].) Step 3: Access the Token in Your Tools As shown in the first point, your tools can now easily access this token from Special Case:
|
Beta Was this translation helpful? Give feedback.
-
|
I would suggest while creating a session, send the token as a payload in the body. Set the key as user:<YOUR_DESIRED_KEY>. Then you can access the key in the tool context. Set a user prefix will make sure it's not shared. https://google.github.io/adk-docs/sessions/state/#organizing-state-with-prefixes-scope-matters |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
How to pass custom HTTP headers (e.g. Authorization) from
/runrequest into ADK tools?Hi 👋
I’m building a Google ADK project where an agent calls external APIs via tools.
Each API request must be authenticated per user, using a session token (JWT / Bearer token).
This project is intended to support many concurrent users (multi-tenant), where each user can only access their own data.
Current setup
adk web)/runendpoint is implemented inside the ADK package (adk_web_server.py)Authorization) to/runExample request
What I want to achieve
For each
/runrequest:Authorization: Bearer <token>)This token should be request-scoped, not global.
What I want to avoid
adk_web_server.pyQuestions
Is there an official way to:
/runinside ADK?Is wrapping ADK with a custom FastAPI / middleware layer the recommended approach for:
Are there any built-in hooks, callbacks, or best practices for propagating per-request context into tools?
Constraints / Notes
Any guidance, best practices, or confirmation of the intended architecture would be greatly appreciated.
Thanks in advance!
Beta Was this translation helpful? Give feedback.
All reactions