jaf-py 2.5.10__py3-none-any.whl → 2.5.11__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. jaf/__init__.py +154 -57
  2. jaf/a2a/__init__.py +42 -21
  3. jaf/a2a/agent.py +79 -126
  4. jaf/a2a/agent_card.py +87 -78
  5. jaf/a2a/client.py +30 -66
  6. jaf/a2a/examples/client_example.py +12 -12
  7. jaf/a2a/examples/integration_example.py +38 -47
  8. jaf/a2a/examples/server_example.py +56 -53
  9. jaf/a2a/memory/__init__.py +0 -4
  10. jaf/a2a/memory/cleanup.py +28 -21
  11. jaf/a2a/memory/factory.py +155 -133
  12. jaf/a2a/memory/providers/composite.py +21 -26
  13. jaf/a2a/memory/providers/in_memory.py +89 -83
  14. jaf/a2a/memory/providers/postgres.py +117 -115
  15. jaf/a2a/memory/providers/redis.py +128 -121
  16. jaf/a2a/memory/serialization.py +77 -87
  17. jaf/a2a/memory/tests/run_comprehensive_tests.py +112 -83
  18. jaf/a2a/memory/tests/test_cleanup.py +211 -94
  19. jaf/a2a/memory/tests/test_serialization.py +73 -68
  20. jaf/a2a/memory/tests/test_stress_concurrency.py +186 -133
  21. jaf/a2a/memory/tests/test_task_lifecycle.py +138 -120
  22. jaf/a2a/memory/types.py +91 -53
  23. jaf/a2a/protocol.py +95 -125
  24. jaf/a2a/server.py +90 -118
  25. jaf/a2a/standalone_client.py +30 -43
  26. jaf/a2a/tests/__init__.py +16 -33
  27. jaf/a2a/tests/run_tests.py +17 -53
  28. jaf/a2a/tests/test_agent.py +40 -140
  29. jaf/a2a/tests/test_client.py +54 -117
  30. jaf/a2a/tests/test_integration.py +28 -82
  31. jaf/a2a/tests/test_protocol.py +54 -139
  32. jaf/a2a/tests/test_types.py +50 -136
  33. jaf/a2a/types.py +58 -34
  34. jaf/cli.py +21 -41
  35. jaf/core/__init__.py +7 -1
  36. jaf/core/agent_tool.py +93 -72
  37. jaf/core/analytics.py +257 -207
  38. jaf/core/checkpoint.py +223 -0
  39. jaf/core/composition.py +249 -235
  40. jaf/core/engine.py +817 -519
  41. jaf/core/errors.py +55 -42
  42. jaf/core/guardrails.py +276 -202
  43. jaf/core/handoff.py +47 -31
  44. jaf/core/parallel_agents.py +69 -75
  45. jaf/core/performance.py +75 -73
  46. jaf/core/proxy.py +43 -44
  47. jaf/core/proxy_helpers.py +24 -27
  48. jaf/core/regeneration.py +220 -129
  49. jaf/core/state.py +68 -66
  50. jaf/core/streaming.py +115 -108
  51. jaf/core/tool_results.py +111 -101
  52. jaf/core/tools.py +114 -116
  53. jaf/core/tracing.py +269 -210
  54. jaf/core/types.py +371 -151
  55. jaf/core/workflows.py +209 -168
  56. jaf/exceptions.py +46 -38
  57. jaf/memory/__init__.py +1 -6
  58. jaf/memory/approval_storage.py +54 -77
  59. jaf/memory/factory.py +4 -4
  60. jaf/memory/providers/in_memory.py +216 -180
  61. jaf/memory/providers/postgres.py +216 -146
  62. jaf/memory/providers/redis.py +173 -116
  63. jaf/memory/types.py +70 -51
  64. jaf/memory/utils.py +36 -34
  65. jaf/plugins/__init__.py +12 -12
  66. jaf/plugins/base.py +105 -96
  67. jaf/policies/__init__.py +0 -1
  68. jaf/policies/handoff.py +37 -46
  69. jaf/policies/validation.py +76 -52
  70. jaf/providers/__init__.py +6 -3
  71. jaf/providers/mcp.py +97 -51
  72. jaf/providers/model.py +360 -279
  73. jaf/server/__init__.py +1 -1
  74. jaf/server/main.py +7 -11
  75. jaf/server/server.py +514 -359
  76. jaf/server/types.py +208 -52
  77. jaf/utils/__init__.py +17 -18
  78. jaf/utils/attachments.py +111 -116
  79. jaf/utils/document_processor.py +175 -174
  80. jaf/visualization/__init__.py +1 -1
  81. jaf/visualization/example.py +111 -110
  82. jaf/visualization/functional_core.py +46 -71
  83. jaf/visualization/graphviz.py +154 -189
  84. jaf/visualization/imperative_shell.py +7 -16
  85. jaf/visualization/types.py +8 -4
  86. {jaf_py-2.5.10.dist-info → jaf_py-2.5.11.dist-info}/METADATA +2 -2
  87. jaf_py-2.5.11.dist-info/RECORD +97 -0
  88. jaf_py-2.5.10.dist-info/RECORD +0 -96
  89. {jaf_py-2.5.10.dist-info → jaf_py-2.5.11.dist-info}/WHEEL +0 -0
  90. {jaf_py-2.5.10.dist-info → jaf_py-2.5.11.dist-info}/entry_points.txt +0 -0
  91. {jaf_py-2.5.10.dist-info → jaf_py-2.5.11.dist-info}/licenses/LICENSE +0 -0
  92. {jaf_py-2.5.10.dist-info → jaf_py-2.5.11.dist-info}/top_level.txt +0 -0
jaf/a2a/server.py CHANGED
@@ -20,30 +20,19 @@ from .types import A2AAgent
20
20
  def create_a2a_server_config(config: Dict[str, Any]) -> Dict[str, Any]:
21
21
  """Pure function to create A2A server configuration"""
22
22
  host = config.get("host", "localhost")
23
- capabilities = config.get("capabilities", {
24
- "streaming": True,
25
- "pushNotifications": False,
26
- "stateTransitionHistory": True
27
- })
23
+ capabilities = config.get(
24
+ "capabilities",
25
+ {"streaming": True, "pushNotifications": False, "stateTransitionHistory": True},
26
+ )
28
27
 
29
28
  agent_card = generate_agent_card(
30
- config["agentCard"],
31
- config["agents"],
32
- f"http://{host}:{config['port']}"
29
+ config["agentCard"], config["agents"], f"http://{host}:{config['port']}"
33
30
  )
34
31
 
35
32
  # Override the capabilities in the generated agent card
36
- updated_agent_card = {
37
- **agent_card,
38
- "capabilities": capabilities
39
- }
33
+ updated_agent_card = {**agent_card, "capabilities": capabilities}
40
34
 
41
- return {
42
- **config,
43
- "host": host,
44
- "capabilities": capabilities,
45
- "agentCard": updated_agent_card
46
- }
35
+ return {**config, "host": host, "capabilities": capabilities, "agentCard": updated_agent_card}
47
36
 
48
37
 
49
38
  def create_fastapi_app() -> FastAPI:
@@ -53,7 +42,7 @@ def create_fastapi_app() -> FastAPI:
53
42
  description="Agent-to-Agent protocol server for JAF",
54
43
  version="1.0.0",
55
44
  docs_url="/docs",
56
- redoc_url="/redoc"
45
+ redoc_url="/redoc",
57
46
  )
58
47
 
59
48
  # Add CORS middleware
@@ -93,8 +82,8 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
93
82
  "error": {
94
83
  "code": -32700, # Parse Error
95
84
  "message": "Parse error",
96
- "data": {"details": str(e)}
97
- }
85
+ "data": {"details": str(e)},
86
+ },
98
87
  }
99
88
  except Exception as e:
100
89
  return {
@@ -103,8 +92,8 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
103
92
  "error": {
104
93
  "code": -32700, # Parse Error
105
94
  "message": "Parse error",
106
- "data": {"details": str(e)}
107
- }
95
+ "data": {"details": str(e)},
96
+ },
108
97
  }
109
98
 
110
99
  # Handle batch requests
@@ -116,8 +105,8 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
116
105
  "error": {
117
106
  "code": -32600, # Invalid Request
118
107
  "message": "Invalid Request",
119
- "data": {"details": "Batch request cannot be empty"}
120
- }
108
+ "data": {"details": "Batch request cannot be empty"},
109
+ },
121
110
  }
122
111
 
123
112
  # Process batch requests functionally
@@ -129,8 +118,8 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
129
118
  "error": {
130
119
  "code": -32600, # Invalid Request
131
120
  "message": "Invalid Request",
132
- "data": {"details": "Each batch item must be an object"}
133
- }
121
+ "data": {"details": "Each batch item must be an object"},
122
+ },
134
123
  }
135
124
 
136
125
  single_result = await handle_a2a_request_internal(config, single_request)
@@ -143,8 +132,8 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
143
132
  "id": single_request.get("id"),
144
133
  "error": {
145
134
  "code": -32005, # Content Type Not Supported
146
- "message": "Streaming not supported in batch requests"
147
- }
135
+ "message": "Streaming not supported in batch requests",
136
+ },
148
137
  }
149
138
 
150
139
  # Process all batch items
@@ -160,8 +149,8 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
160
149
  "error": {
161
150
  "code": -32600, # Invalid Request
162
151
  "message": "Invalid Request",
163
- "data": {"details": "Request must be an object"}
164
- }
152
+ "data": {"details": "Request must be an object"},
153
+ },
165
154
  }
166
155
 
167
156
  result = await handle_a2a_request_internal(config, body)
@@ -171,6 +160,7 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
171
160
  if method == "message/stream":
172
161
  # For streaming, result should be an async generator
173
162
  if hasattr(result, "__aiter__"):
163
+
174
164
  async def generate_sse():
175
165
  async for chunk in result:
176
166
  yield f"data: {json.dumps(chunk)}\n\n"
@@ -178,10 +168,7 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
178
168
  return StreamingResponse(
179
169
  generate_sse(),
180
170
  media_type="text/event-stream",
181
- headers={
182
- "Cache-Control": "no-cache",
183
- "Connection": "keep-alive"
184
- }
171
+ headers={"Cache-Control": "no-cache", "Connection": "keep-alive"},
185
172
  )
186
173
  else:
187
174
  # If it's not iterable, wrap single response
@@ -191,10 +178,7 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
191
178
  return StreamingResponse(
192
179
  generate_sse(),
193
180
  media_type="text/event-stream",
194
- headers={
195
- "Cache-Control": "no-cache",
196
- "Connection": "keep-alive"
197
- }
181
+ headers={"Cache-Control": "no-cache", "Connection": "keep-alive"},
198
182
  )
199
183
 
200
184
  return result
@@ -202,6 +186,7 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
202
186
  except Exception as error:
203
187
  # Log the error for debugging but don't expose internal details
204
188
  import logging
189
+
205
190
  logging.error(f"Internal server error: {error!s}")
206
191
 
207
192
  return {
@@ -210,8 +195,8 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
210
195
  "error": {
211
196
  "code": -32603, # Internal Error
212
197
  "message": "Internal error",
213
- "data": {"type": "server_error"}
214
- }
198
+ "data": {"type": "server_error"},
199
+ },
215
200
  }
216
201
 
217
202
  # Agent-specific endpoints
@@ -233,8 +218,8 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
233
218
  "error": {
234
219
  "code": -32700, # Parse Error
235
220
  "message": "Parse error",
236
- "data": {"details": str(e)}
237
- }
221
+ "data": {"details": str(e)},
222
+ },
238
223
  }
239
224
  except Exception as e:
240
225
  return {
@@ -243,8 +228,8 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
243
228
  "error": {
244
229
  "code": -32700, # Parse Error
245
230
  "message": "Parse error",
246
- "data": {"details": str(e)}
247
- }
231
+ "data": {"details": str(e)},
232
+ },
248
233
  }
249
234
 
250
235
  # Validate request structure
@@ -255,8 +240,8 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
255
240
  "error": {
256
241
  "code": -32600, # Invalid Request
257
242
  "message": "Invalid Request",
258
- "data": {"details": "Request must be an object"}
259
- }
243
+ "data": {"details": "Request must be an object"},
244
+ },
260
245
  }
261
246
 
262
247
  result = await handle_a2a_request_for_agent(config, body, agent_name)
@@ -266,6 +251,7 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
266
251
  if method == "message/stream":
267
252
  # For streaming, result should be an async generator
268
253
  if hasattr(result, "__aiter__"):
254
+
269
255
  async def generate_sse():
270
256
  async for chunk in result:
271
257
  yield f"data: {json.dumps(chunk)}\n\n"
@@ -273,10 +259,7 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
273
259
  return StreamingResponse(
274
260
  generate_sse(),
275
261
  media_type="text/event-stream",
276
- headers={
277
- "Cache-Control": "no-cache",
278
- "Connection": "keep-alive"
279
- }
262
+ headers={"Cache-Control": "no-cache", "Connection": "keep-alive"},
280
263
  )
281
264
  else:
282
265
  # If it's not iterable, wrap single response
@@ -286,10 +269,7 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
286
269
  return StreamingResponse(
287
270
  generate_sse(),
288
271
  media_type="text/event-stream",
289
- headers={
290
- "Cache-Control": "no-cache",
291
- "Connection": "keep-alive"
292
- }
272
+ headers={"Cache-Control": "no-cache", "Connection": "keep-alive"},
293
273
  )
294
274
 
295
275
  return result
@@ -297,6 +277,7 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
297
277
  except Exception as error:
298
278
  # Log the error for debugging but don't expose internal details
299
279
  import logging
280
+
300
281
  logging.error(f"Internal server error: {error!s}")
301
282
 
302
283
  return {
@@ -305,8 +286,8 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
305
286
  "error": {
306
287
  "code": -32603, # Internal Error
307
288
  "message": "Internal error",
308
- "data": {"type": "server_error"}
309
- }
289
+ "data": {"type": "server_error"},
290
+ },
310
291
  }
311
292
 
312
293
  # Agent-specific card endpoint - fix closure issue
@@ -318,16 +299,16 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
318
299
  "name": current_agent.name,
319
300
  "description": current_agent.description,
320
301
  "version": "1.0.0",
321
- "provider": config["agentCard"].get("provider", {
322
- "organization": "Unknown",
323
- "url": ""
324
- })
302
+ "provider": config["agentCard"].get(
303
+ "provider", {"organization": "Unknown", "url": ""}
304
+ ),
325
305
  },
326
306
  {current_agent_name: current_agent},
327
- f"http://{config.get('host', 'localhost')}:{config['port']}"
307
+ f"http://{config.get('host', 'localhost')}:{config['port']}",
328
308
  )
329
309
 
330
310
  return agent_card
311
+
331
312
  return get_agent_card_specific
332
313
 
333
314
  # Create the endpoint with proper closure
@@ -341,7 +322,7 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
341
322
  "protocol": "A2A",
342
323
  "version": "0.3.0",
343
324
  "agents": list(config["agents"].keys()),
344
- "timestamp": None # Would be set by the system
325
+ "timestamp": None, # Would be set by the system
345
326
  }
346
327
 
347
328
  # A2A capabilities endpoint
@@ -353,19 +334,16 @@ def setup_a2a_routes(app: FastAPI, config: Dict[str, Any]) -> None:
353
334
  "message/stream",
354
335
  "tasks/get",
355
336
  "tasks/cancel",
356
- "agent/getAuthenticatedExtendedCard"
337
+ "agent/getAuthenticatedExtendedCard",
357
338
  ],
358
339
  "supportedTransports": ["JSONRPC"],
359
340
  "capabilities": config["agentCard"]["capabilities"],
360
341
  "inputModes": config["agentCard"]["defaultInputModes"],
361
- "outputModes": config["agentCard"]["defaultOutputModes"]
342
+ "outputModes": config["agentCard"]["defaultOutputModes"],
362
343
  }
363
344
 
364
345
 
365
- async def handle_a2a_request_internal(
366
- config: Dict[str, Any],
367
- request: Dict[str, Any]
368
- ) -> Any:
346
+ async def handle_a2a_request_internal(config: Dict[str, Any], request: Dict[str, Any]) -> Any:
369
347
  """Pure function to handle A2A requests"""
370
348
  # Validate JSON-RPC request structure first
371
349
  if not validate_jsonrpc_request(request):
@@ -375,15 +353,18 @@ async def handle_a2a_request_internal(
375
353
  "error": {
376
354
  "code": -32600, # Invalid Request
377
355
  "message": "Invalid Request",
378
- "data": {"details": "Missing required JSON-RPC fields"}
379
- }
356
+ "data": {"details": "Missing required JSON-RPC fields"},
357
+ },
380
358
  }
381
359
 
382
360
  # Check if method is supported
383
361
  method = request.get("method")
384
362
  supported_methods = [
385
- "message/send", "message/stream", "tasks/get",
386
- "tasks/cancel", "agent/getAuthenticatedExtendedCard"
363
+ "message/send",
364
+ "message/stream",
365
+ "tasks/get",
366
+ "tasks/cancel",
367
+ "agent/getAuthenticatedExtendedCard",
387
368
  ]
388
369
 
389
370
  if method not in supported_methods:
@@ -393,8 +374,8 @@ async def handle_a2a_request_internal(
393
374
  "error": {
394
375
  "code": -32601, # Method Not Found
395
376
  "message": f"Method '{method}' not found",
396
- "data": {"supported_methods": supported_methods}
397
- }
377
+ "data": {"supported_methods": supported_methods},
378
+ },
398
379
  }
399
380
 
400
381
  # Use the first available agent by default
@@ -403,10 +384,7 @@ async def handle_a2a_request_internal(
403
384
  return {
404
385
  "jsonrpc": "2.0",
405
386
  "id": request.get("id"),
406
- "error": {
407
- "code": -32001,
408
- "message": "No agents available"
409
- }
387
+ "error": {"code": -32001, "message": "No agents available"},
410
388
  }
411
389
 
412
390
  first_agent = next(iter(agents.values()))
@@ -414,9 +392,7 @@ async def handle_a2a_request_internal(
414
392
 
415
393
 
416
394
  async def handle_a2a_request_for_agent(
417
- config: Dict[str, Any],
418
- request: Dict[str, Any],
419
- agent_name: str
395
+ config: Dict[str, Any], request: Dict[str, Any], agent_name: str
420
396
  ) -> Any:
421
397
  """Pure function to handle agent-specific A2A requests"""
422
398
  # Validate JSON-RPC request structure first
@@ -427,15 +403,18 @@ async def handle_a2a_request_for_agent(
427
403
  "error": {
428
404
  "code": -32600, # Invalid Request
429
405
  "message": "Invalid Request",
430
- "data": {"details": "Missing required JSON-RPC fields"}
431
- }
406
+ "data": {"details": "Missing required JSON-RPC fields"},
407
+ },
432
408
  }
433
409
 
434
410
  # Check if method is supported
435
411
  method = request.get("method")
436
412
  supported_methods = [
437
- "message/send", "message/stream", "tasks/get",
438
- "tasks/cancel", "agent/getAuthenticatedExtendedCard"
413
+ "message/send",
414
+ "message/stream",
415
+ "tasks/get",
416
+ "tasks/cancel",
417
+ "agent/getAuthenticatedExtendedCard",
439
418
  ]
440
419
 
441
420
  if method not in supported_methods:
@@ -445,8 +424,8 @@ async def handle_a2a_request_for_agent(
445
424
  "error": {
446
425
  "code": -32601, # Method Not Found
447
426
  "message": f"Method '{method}' not found",
448
- "data": {"supported_methods": supported_methods}
449
- }
427
+ "data": {"supported_methods": supported_methods},
428
+ },
450
429
  }
451
430
 
452
431
  agent = config["agents"].get(agent_name)
@@ -454,19 +433,14 @@ async def handle_a2a_request_for_agent(
454
433
  return {
455
434
  "jsonrpc": "2.0",
456
435
  "id": request.get("id"),
457
- "error": {
458
- "code": -32001,
459
- "message": f"Agent {agent_name} not found"
460
- }
436
+ "error": {"code": -32001, "message": f"Agent {agent_name} not found"},
461
437
  }
462
438
 
463
439
  return await route_a2a_request_wrapper(config, request, agent)
464
440
 
465
441
 
466
442
  async def route_a2a_request_wrapper(
467
- config: Dict[str, Any],
468
- request: Dict[str, Any],
469
- agent: A2AAgent
443
+ config: Dict[str, Any], request: Dict[str, Any], agent: A2AAgent
470
444
  ) -> Any:
471
445
  """Wrapper for route_a2a_request to provide required dependencies"""
472
446
  try:
@@ -482,7 +456,7 @@ async def route_a2a_request_wrapper(
482
456
  task_storage,
483
457
  agent_card,
484
458
  execute_a2a_agent,
485
- execute_a2a_agent_with_streaming
459
+ execute_a2a_agent_with_streaming,
486
460
  )
487
461
 
488
462
  # Check if result is a coroutine/awaitable
@@ -499,6 +473,7 @@ async def route_a2a_request_wrapper(
499
473
  except Exception as e:
500
474
  # Return proper JSON-RPC error
501
475
  import logging
476
+
502
477
  logging.error(f"Route wrapper error: {e!s}")
503
478
 
504
479
  return {
@@ -507,8 +482,8 @@ async def route_a2a_request_wrapper(
507
482
  "error": {
508
483
  "code": -32603, # Internal Error
509
484
  "message": "Internal error",
510
- "data": {"type": "route_error"}
511
- }
485
+ "data": {"type": "route_error"},
486
+ },
512
487
  }
513
488
 
514
489
 
@@ -523,7 +498,7 @@ def create_a2a_server(config: Dict[str, Any]) -> Dict[str, Any]:
523
498
  app,
524
499
  host=server_config.get("host", "localhost"),
525
500
  port=server_config["port"],
526
- log_level="info"
501
+ log_level="info",
527
502
  )
528
503
  server = uvicorn.Server(uvicorn_config)
529
504
 
@@ -561,14 +536,13 @@ def create_a2a_server(config: Dict[str, Any]) -> Dict[str, Any]:
561
536
  "agentCard": generate_agent_card(
562
537
  {
563
538
  **server_config["agentCard"],
564
- "provider": server_config["agentCard"].get("provider", {
565
- "organization": "Unknown",
566
- "url": ""
567
- })
539
+ "provider": server_config["agentCard"].get(
540
+ "provider", {"organization": "Unknown", "url": ""}
541
+ ),
568
542
  },
569
543
  new_agents,
570
- server_config["agentCard"]["url"].replace("/a2a", "")
571
- )
544
+ server_config["agentCard"]["url"].replace("/a2a", ""),
545
+ ),
572
546
  }
573
547
 
574
548
  def remove_agent(name: str) -> Dict[str, Any]:
@@ -581,14 +555,13 @@ def create_a2a_server(config: Dict[str, Any]) -> Dict[str, Any]:
581
555
  "agentCard": generate_agent_card(
582
556
  {
583
557
  **server_config["agentCard"],
584
- "provider": server_config["agentCard"].get("provider", {
585
- "organization": "Unknown",
586
- "url": ""
587
- })
558
+ "provider": server_config["agentCard"].get(
559
+ "provider", {"organization": "Unknown", "url": ""}
560
+ ),
588
561
  },
589
562
  new_agents,
590
- server_config["agentCard"]["url"].replace("/a2a", "")
591
- )
563
+ server_config["agentCard"]["url"].replace("/a2a", ""),
564
+ ),
592
565
  }
593
566
 
594
567
  return {
@@ -598,7 +571,7 @@ def create_a2a_server(config: Dict[str, Any]) -> Dict[str, Any]:
598
571
  "stop": stop_server,
599
572
  "add_agent": add_agent,
600
573
  "remove_agent": remove_agent,
601
- "get_agent_card": lambda: server_config["agentCard"]
574
+ "get_agent_card": lambda: server_config["agentCard"],
602
575
  }
603
576
 
604
577
 
@@ -611,6 +584,7 @@ async def start_a2a_server(config: Dict[str, Any]) -> Dict[str, Any]:
611
584
 
612
585
  # Utility functions for configuration
613
586
 
587
+
614
588
  def create_server_config(
615
589
  agents: Dict[str, A2AAgent],
616
590
  name: str,
@@ -618,7 +592,7 @@ def create_server_config(
618
592
  port: int,
619
593
  host: str = "localhost",
620
594
  version: str = "1.0.0",
621
- provider: Optional[Dict[str, str]] = None
595
+ provider: Optional[Dict[str, str]] = None,
622
596
  ) -> Dict[str, Any]:
623
597
  """Utility function to create server configuration"""
624
598
  return {
@@ -627,11 +601,9 @@ def create_server_config(
627
601
  "name": name,
628
602
  "description": description,
629
603
  "version": version,
630
- "provider": provider or {
631
- "organization": "JAF Framework",
632
- "url": "https://functional-agent-framework.com"
633
- }
604
+ "provider": provider
605
+ or {"organization": "JAF Framework", "url": "https://functional-agent-framework.com"},
634
606
  },
635
607
  "port": port,
636
- "host": host
608
+ "host": host,
637
609
  }