44from textwrap import dedent
55
66import uvicorn
7+ from starlette .applications import Starlette
78
9+ from a2a .helpers import new_task_from_user_message
810from a2a .server .agent_execution import AgentExecutor , RequestContext
9- from a2a .server .apps import A2AStarletteApplication
1011from a2a .server .events .event_queue import EventQueue
1112from a2a .server .request_handlers import DefaultRequestHandler
13+ from a2a .server .routes import create_agent_card_routes , create_jsonrpc_routes
1214from a2a .server .tasks import InMemoryTaskStore , TaskUpdater
13- from a2a .types import AgentCapabilities , AgentCard , AgentSkill
14- from a2a .utils import new_task
15+ from a2a .types import AgentCapabilities , AgentCard , AgentInterface , AgentSkill
1516from claude_agent .configuration import Configuration
1617from claude_agent .events import StreamTranslator
1718from claude_agent .runner import run_turn
@@ -46,7 +47,12 @@ def get_agent_card(host: str, port: int) -> AgentCard:
4647 - **prompt** (string) – the instruction or question for Claude.
4748 """
4849 ),
49- url = os .getenv ("AGENT_ENDPOINT" , f"http://{ host } :{ port } " ).rstrip ("/" ) + "/" ,
50+ supported_interfaces = [
51+ AgentInterface (
52+ url = os .getenv ("AGENT_ENDPOINT" , f"http://{ host } :{ port } " ).rstrip ("/" ) + "/" ,
53+ protocol_binding = "JSONRPC" ,
54+ )
55+ ],
5056 version = "1.0.0" ,
5157 default_input_modes = ["text" ],
5258 default_output_modes = ["text" ],
@@ -71,7 +77,7 @@ def __init__(
7177 async def execute (self , context : RequestContext , event_queue : EventQueue ) -> None :
7278 task = context .current_task
7379 if not task :
74- task = new_task (context .message ) # type: ignore
80+ task = new_task_from_user_message (context .message ) # type: ignore
7581 await event_queue .enqueue_event (task )
7682 task_updater = TaskUpdater (event_queue , task .id , task .context_id )
7783 translator = StreamTranslator (task_updater )
@@ -118,11 +124,16 @@ def run() -> None:
118124 request_handler = DefaultRequestHandler (
119125 agent_executor = ClaudeAgentExecutor (config , registry , semaphore ),
120126 task_store = InMemoryTaskStore (),
127+ agent_card = agent_card ,
121128 )
122- server = A2AStarletteApplication (agent_card = agent_card , http_handler = request_handler )
123- # build() serves the agent card at /.well-known/agent-card.json natively
124- # (a2a-sdk's default AGENT_CARD_WELL_KNOWN_PATH), plus the legacy
125- # /.well-known/agent.json for back-compat — no custom route needed.
126- app = server .build ()
129+ # a2a-sdk 1.x replaced A2AStarletteApplication with route factories that we
130+ # assemble into a Starlette app ourselves. Serve the current well-known path
131+ # (/.well-known/agent-card.json) plus the legacy /.well-known/agent.json for
132+ # back-compat.
133+ # enable_v0_3_compat is needed because Kagenti uses A2A 0.3 client libraries
134+ routes = create_jsonrpc_routes (request_handler , rpc_url = "/" , enable_v0_3_compat = True )
135+ routes += create_agent_card_routes (agent_card )
136+ routes += create_agent_card_routes (agent_card , card_url = "/.well-known/agent.json" )
137+ app = Starlette (routes = routes )
127138
128139 uvicorn .run (app , host = config .host , port = config .port )
0 commit comments