11from typing import Any , List , cast
2- import fnmatch
32
43from agentex import AsyncAgentex
54from agentex .lib .core .tracing .tracer import AsyncTracer
1110from agentex .types .task_message import TaskMessage
1211from agentex .types .task_message_content import TaskMessageContent
1312from agentex .types .task_message_content_param import TaskMessageContentParam
13+ from agentex .types .agent_rpc_params import (
14+ ParamsCancelTaskRequest as RpcParamsCancelTaskRequest ,
15+ ParamsSendEventRequest as RpcParamsSendEventRequest ,
16+ )
1417
1518logger = make_logger (__name__ )
1619
@@ -24,77 +27,6 @@ def __init__(
2427 self ._agentex_client = agentex_client
2528 self ._tracer = tracer
2629
27- async def _get_agent_header_allowlist (
28- self , agent_name : str | None = None , agent_id : str | None = None
29- ) -> list [str ] | None :
30- """
31- Get agent's header allowlist from manifest.
32-
33- Returns None for pass-through behavior (all headers forwarded).
34- Returns list[str] of allowed header patterns if agent has filtering requirements.
35-
36- Note: In a production system, this would load the agent's manifest from a registry/database
37- based on agent_name/agent_id and return the header_allowlist. For now, we implement
38- pass-through by default as requested.
39-
40- TODO: Integrate with agent registry to load manifest-based header allowlists
41- """
42- # Pass-through by default - forward all headers unless agent has specific filtering config
43- # In production, this would query an agent registry/database:
44- # 1. Look up agent by name/id
45- # 2. Get agent's manifest configuration
46- # 3. Return manifest.agent.header_allowlist
47- return None
48-
49- def _filter_headers (
50- self ,
51- headers : dict [str , str ] | None ,
52- allowlist : list [str ] | None
53- ) -> dict [str , str ]:
54- """
55- Filter headers based on agent's allowlist.
56-
57- Pass-through by default: if no allowlist provided, all headers are forwarded.
58- If allowlist exists, only matching headers are forwarded.
59-
60- Args:
61- headers: Headers to filter
62- allowlist: Agent's header allowlist (None = pass-through all)
63-
64- Returns:
65- Filtered headers dictionary
66- """
67- if not headers :
68- return {}
69-
70- # Pass-through behavior: if no allowlist, forward all headers
71- if allowlist is None :
72- logger .info ("No header allowlist found, passing through all %d headers" , len (headers ))
73- return headers
74-
75- # Apply filtering based on allowlist
76- if not allowlist :
77- logger .info ("Empty allowlist, blocking all headers" )
78- return {}
79-
80- filtered = {}
81- for header_name , header_value in headers .items ():
82- # Check against allowlist patterns (case-insensitive)
83- header_allowed = False
84- for pattern in allowlist :
85- if fnmatch .fnmatch (header_name .lower (), pattern .lower ()):
86- header_allowed = True
87- break
88-
89- if header_allowed :
90- filtered [header_name ] = header_value
91- logger .info ("Allowed header: %s" , header_name )
92- else :
93- logger .info ("Header '%s' not in allowlist, ignoring" , header_name )
94-
95- logger .info ("Filtered %d headers from %d based on allowlist" , len (filtered ), len (headers ))
96- return filtered
97-
9830 async def task_create (
9931 self ,
10032 name : str | None = None ,
@@ -118,10 +50,9 @@ async def task_create(
11850 ) as span :
11951 heartbeat_if_in_workflow ("task create" )
12052
121- # Extract headers from request and filter them
53+ # Extract headers from request; pass-through to agent
12254 headers = request .get ("headers" ) if request else None
123- header_allowlist = await self ._get_agent_header_allowlist (agent_name , agent_id )
124- filtered_headers = self ._filter_headers (headers , header_allowlist )
55+ filtered_headers : dict [str , str ] = headers or {}
12556
12657 if agent_name :
12758 json_rpc_response = await self ._agentex_client .agents .rpc_by_name (
@@ -176,10 +107,9 @@ async def message_send(
176107 ) as span :
177108 heartbeat_if_in_workflow ("message send" )
178109
179- # Extract headers from request and filter them
110+ # Extract headers from request; pass-through to agent
180111 headers = request .get ("headers" ) if request else None
181- header_allowlist = await self ._get_agent_header_allowlist (agent_name , agent_id )
182- filtered_headers = self ._filter_headers (headers , header_allowlist )
112+ filtered_headers : dict [str , str ] = headers or {}
183113
184114 if agent_name :
185115 json_rpc_response = await self ._agentex_client .agents .rpc_by_name (
@@ -238,34 +168,33 @@ async def event_send(
238168 "agent_id" : agent_id ,
239169 "agent_name" : agent_name ,
240170 "task_id" : task_id ,
171+ "task_name" : task_name ,
241172 "content" : content ,
242173 },
243174 ) as span :
244175 heartbeat_if_in_workflow ("event send" )
245176
246- # Extract headers from request and filter them
177+ # Extract headers from request; pass-through to agent
247178 headers = request .get ("headers" ) if request else None
248- header_allowlist = await self ._get_agent_header_allowlist (agent_name , agent_id )
249- filtered_headers = self ._filter_headers (headers , header_allowlist )
179+ filtered_headers : dict [str , str ] = headers or {}
250180
181+ rpc_event_params : RpcParamsSendEventRequest = {
182+ "task_id" : task_id ,
183+ "task_name" : task_name ,
184+ "content" : cast (TaskMessageContentParam , content .model_dump ()),
185+ }
251186 if agent_name :
252187 json_rpc_response = await self ._agentex_client .agents .rpc_by_name (
253188 agent_name = agent_name ,
254189 method = "event/send" ,
255- params = {
256- "task_id" : task_id ,
257- "content" : cast (TaskMessageContentParam , content .model_dump ()),
258- },
190+ params = rpc_event_params ,
259191 extra_headers = filtered_headers ,
260192 )
261193 elif agent_id :
262194 json_rpc_response = await self ._agentex_client .agents .rpc (
263195 agent_id = agent_id ,
264196 method = "event/send" ,
265- params = {
266- "task_id" : task_id ,
267- "content" : cast (TaskMessageContentParam , content .model_dump ()),
268- },
197+ params = rpc_event_params ,
269198 extra_headers = filtered_headers ,
270199 )
271200 else :
@@ -296,7 +225,7 @@ async def task_cancel(
296225 agent_name: Name of the agent that owns the task
297226 trace_id: Trace ID for tracing
298227 parent_span_id: Parent span ID for tracing
299- extra_headers: Headers to forward to the agent
228+ request: Additional request context including headers to forward to the agent
300229
301230 Returns:
302231 Task entry representing the cancelled task
@@ -325,13 +254,12 @@ async def task_cancel(
325254 ) as span :
326255 heartbeat_if_in_workflow ("task cancel" )
327256
328- # Extract headers from request and filter them
257+ # Extract headers from request; pass-through to agent
329258 headers = request .get ("headers" ) if request else None
330- header_allowlist = await self ._get_agent_header_allowlist (agent_name , agent_id )
331- filtered_headers = self ._filter_headers (headers , header_allowlist )
259+ filtered_headers : dict [str , str ] = headers or {}
332260
333261 # Build params for the agent (task identification)
334- params = {}
262+ params : RpcParamsCancelTaskRequest = {}
335263 if task_id :
336264 params ["task_id" ] = task_id
337265 if task_name :
@@ -346,6 +274,7 @@ async def task_cancel(
346274 extra_headers = filtered_headers ,
347275 )
348276 else : # agent_id is provided (validated above)
277+ assert agent_id is not None
349278 json_rpc_response = await self ._agentex_client .agents .rpc (
350279 agent_id = agent_id ,
351280 method = "task/cancel" ,
0 commit comments