1+ """
2+ Example of the business logic of an A2A agent for currency conversion.
3+ """
4+
15import logging
6+ import os
7+
8+ from app .agent import CurrencyAgent
9+
10+ from openai import AuthenticationError , InternalServerError
211
312from a2a .server .agent_execution import AgentExecutor , RequestContext
413from a2a .server .events import EventQueue
1827)
1928from a2a .utils .errors import ServerError
2029
21- from app .agent import CurrencyAgent
22-
23-
2430logging .basicConfig (level = logging .INFO )
2531logger = logging .getLogger (__name__ )
2632
@@ -38,12 +44,14 @@ async def execute(
3844 ) -> None :
3945 error = self ._validate_request (context )
4046 if error :
47+ logger .warning (f'Invalid agent executor request: { context } ' )
4148 raise ServerError (error = InvalidParamsError ())
4249
4350 query = context .get_user_input ()
4451 task = context .current_task
4552 if not task :
4653 task = new_task (context .message )
54+ logger .info (f'Created task for message : { context .message } ' )
4755 event_queue .enqueue_event (task )
4856 updater = TaskUpdater (event_queue , task .id , task .contextId )
4957 try :
@@ -52,6 +60,7 @@ async def execute(
5260 require_user_input = item ['require_user_input' ]
5361
5462 if not is_task_complete and not require_user_input :
63+ logger .info (f'Updating status for non-input task: { task .id } ' )
5564 updater .update_status (
5665 TaskState .working ,
5766 new_agent_text_message (
@@ -61,6 +70,7 @@ async def execute(
6170 ),
6271 )
6372 elif require_user_input :
73+ logger .info (f'Updating status for input task: { task .id } ' )
6474 updater .update_status (
6575 TaskState .input_required ,
6676 new_agent_text_message (
@@ -72,21 +82,78 @@ async def execute(
7282 )
7383 break
7484 else :
85+ logger .info ('Adding artifact for item' )
7586 updater .add_artifact (
7687 [Part (root = TextPart (text = item ['content' ]))],
7788 name = 'conversion_result' ,
7889 )
7990 updater .complete ()
8091 break
8192
93+ except InternalServerError as e :
94+ msg = f"""CurrencyAgentExecutor reports an InternalServerError error.
95+
96+ This can happen if the agent's LLM_API_BASE environment variable does not point to an OpenAI server.
97+
98+ LLM_API_BASE is { os .getenv ("LLM_API_BASE" , "undefined" )}
99+
100+ Use `kubectl -n <namespace> logs deployment/<agent-name>` for details.
101+ """
102+ logger .error (msg = msg )
103+ logger .error (msg = f"Raw InternalServerError: { e } " )
104+ updater .update_status (
105+ TaskState .input_required ,
106+ new_agent_text_message (
107+ msg ,
108+ task .contextId ,
109+ task .id ,
110+ ),
111+ final = True ,
112+ )
113+
114+ except AuthenticationError as e :
115+ msg = f"""CurrencyAgentExecutor reports an authentication error.
116+
117+ When importing this agent into Kagenti, expand Environment Variables and Add Variable,
118+ or import https://github.com/kagenti/agent-examples/blob/main/a2a/a2a_currency_converter/.env.openai
119+
120+ Use `kubectl -n <namespace> logs deployment/<agent-name>` for details.
121+
122+ Also check
123+ `kubectl -n <namespace> get secret openai-secret -o jsonpath="{ '{' } .data.apikey{ '}' } " | base64 -d`
124+ The key should match your OpenAI key."""
125+ logger .error (msg = msg )
126+ logger .error (msg = f"Raw AuthenticationError { e } " )
127+ updater .update_status (
128+ TaskState .input_required ,
129+ new_agent_text_message (
130+ msg ,
131+ task .contextId ,
132+ task .id ,
133+ ),
134+ final = True ,
135+ )
136+
82137 except Exception as e :
83138 logger .error (f'An error occurred while streaming the response: { e } ' )
139+ logger .info (msg = f'The error is a { type (e )} ' )
140+ updater .update_status (
141+ TaskState .input_required ,
142+ new_agent_text_message (
143+ # We don't show the error to the user, as it may have credentials
144+ """Internal error on the agent.
145+ Use `kubectl -n <namespace> logs deployment/<agent-name>` for details""" ,
146+ task .contextId ,
147+ task .id ,
148+ ),
149+ final = True ,
150+ )
84151 raise ServerError (error = InternalError ()) from e
85152
86- def _validate_request (self , context : RequestContext ) -> bool :
153+ def _validate_request (self , _ : RequestContext ) -> bool :
87154 return False
88155
89156 async def cancel (
90- self , request : RequestContext , event_queue : EventQueue
157+ self , _ : RequestContext , event_queue : EventQueue
91158 ) -> Task | None :
92159 raise ServerError (error = UnsupportedOperationError ())
0 commit comments