1414from src .domain .repositories .task_repository import DTaskRepository
1515from src .domain .repositories .task_state_repository import DTaskStateRepository
1616from src .domain .services .agent_acp_service import DAgentACPService
17+ from src .domain .services .authorization_service import DAuthorizationService
1718from src .utils .ids import orm_id
1819from src .utils .logging import make_logger
1920from src .utils .stream_topics import get_task_event_stream_topic
2021
2122logger = make_logger (__name__ )
2223
2324
25+ def _principal_field (principal_context : Any , key : str ) -> str | None :
26+ """Read an attribute from the principal context, which may be either a
27+ Pydantic-style object or a plain dict. The authn proxy returns a dict
28+ (``response.json()`` shape), so ``getattr`` alone silently yields None."""
29+ if principal_context is None :
30+ return None
31+ if isinstance (principal_context , dict ):
32+ return principal_context .get (key )
33+ return getattr (principal_context , key , None )
34+
35+
2436class AgentTaskService :
2537 """
2638 Service for managing agent tasks and forwarding operations to ACP servers.
@@ -33,12 +45,14 @@ def __init__(
3345 task_repository : DTaskRepository ,
3446 event_repository : DEventRepository ,
3547 stream_repository : DRedisStreamRepository ,
48+ authorization_service : DAuthorizationService ,
3649 ):
3750 self .acp_client = acp_client
3851 self .task_state_repository = task_state_repository
3952 self .task_repository = task_repository
4053 self .event_repository = event_repository
4154 self .stream_repository = stream_repository
55+ self .authorization_service = authorization_service
4256
4357 async def create_task (
4458 self ,
@@ -49,16 +63,12 @@ async def create_task(
4963 ) -> TaskEntity :
5064 """
5165 Create a new task record in the repository with single agent (maintains existing interface).
52-
53- Args:
54- agent: The agent to create the task for
55- task_name: The name of the task to be created
56- task_params: The parameters for the task
57- task_metadata: Caller-provided metadata to persist on the task row.
58- Not forwarded to the agent.
59- Returns:
60- Task containing the created task info
6166 """
67+ principal_context = self .authorization_service .principal_context
68+ creator_user_id = _principal_field (principal_context , "user_id" )
69+ creator_service_account_id = _principal_field (
70+ principal_context , "service_account_id"
71+ )
6272
6373 task_entity = await self .task_repository .create (
6474 agent_id = agent .id ,
@@ -69,6 +79,8 @@ async def create_task(
6979 status_reason = "Task created, forwarding to ACP server" ,
7080 params = task_params ,
7181 task_metadata = task_metadata ,
82+ creator_user_id = creator_user_id ,
83+ creator_service_account_id = creator_service_account_id ,
7284 ),
7385 )
7486 return task_entity
@@ -82,16 +94,11 @@ async def create_task_and_forward_to_acp(
8294 """
8395 Create a new task record in the repository with single agent (maintains existing interface).
8496 Then, forward the task to the ACP server.
85-
86- Args:
87- agent: The agent to create the task for
88- task_params: The parameters for the task to be sent to the ACP server
89-
90- Returns:
91- Task containing the created task info
9297 """
9398 task_entity = await self .create_task (
94- agent = agent , task_name = task_name , task_params = task_params
99+ agent = agent ,
100+ task_name = task_name ,
101+ task_params = task_params ,
95102 )
96103
97104 if agent .acp_type == ACPType .SYNC :
0 commit comments