Skip to content

Commit fe26fa1

Browse files
committed
Refactor to make starlette optional
1 parent abfa743 commit fe26fa1

File tree

7 files changed

+744
-677
lines changed

7 files changed

+744
-677
lines changed

README.md

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,35 +26,28 @@ You can install the A2A SDK using either `uv` or `pip`.
2626

2727
### Using `uv`
2828

29-
When you're working within a uv project or a virtual environment managed by uv, the preferred way to add packages is using uv add.
30-
3129
```bash
3230
uv add a2a-sdk
3331
```
3432

35-
### Using `pip`
36-
37-
If you prefer to use pip, the standard Python package installer, you can install `a2a-sdk` as follows
33+
To include the optional HTTP server components (FastAPI, Starlette), install the `http-server` extra:
3834

3935
```bash
40-
pip install a2a-sdk
36+
uv add a2a-sdk[http-server]
4137
```
4238

43-
### Optional
44-
45-
#### FastAPI-based A2A Server App
39+
### Using `pip`
4640

47-
Using `a2a.server.apps.A2AFastAPIApplication` requires the FastAPI package, which is an optional dependency.
48-
With `uv`, it can be specified as follows:
41+
You can install `a2a-sdk` using pip, the standard Python package installer.
4942

50-
```shell
51-
uv add a2a-sdk[fastapi]
43+
```bash
44+
pip install a2a-sdk
5245
```
5346

54-
Alternatively, a preferred version of the `fastapi` package can be added directly to the project:
47+
To include the optional HTTP server components (FastAPI, Starlette), install the `http-server` extra:
5548

56-
```shell
57-
uv add fastapi
49+
```bash
50+
pip install a2a-sdk[http-server]
5851
```
5952

6053
## Examples

pyproject.toml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ dependencies = [
1414
"opentelemetry-api>=1.33.0",
1515
"opentelemetry-sdk>=1.33.0",
1616
"pydantic>=2.11.3",
17-
"sse-starlette",
18-
"starlette",
1917
"grpcio>=1.60",
2018
"grpcio-tools>=1.60",
2119
"grpcio_reflection>=1.7.0",
@@ -35,6 +33,9 @@ classifiers = [
3533
"License :: OSI Approved :: Apache Software License",
3634
]
3735

36+
[project.optional-dependencies]
37+
http-server = ["fastapi>=0.115.2", "sse-starlette", "starlette"]
38+
3839
[project.urls]
3940
homepage = "https://google-a2a.github.io/A2A/"
4041
repository = "https://github.com/google-a2a/a2a-python"
@@ -51,7 +52,7 @@ python_functions = "test_*"
5152
addopts = "-ra --strict-markers"
5253
asyncio_mode = "strict"
5354
markers = [
54-
"asyncio: mark a test as a coroutine that should be run by pytest-asyncio",
55+
"asyncio: mark a test as a coroutine that should be run by pytest-asyncio",
5556
]
5657

5758
[build-system]
@@ -83,9 +84,8 @@ dev = [
8384
"types-requests",
8485
"pre-commit",
8586
"fastapi>=0.115.2",
86-
]
87-
fastapi = [
88-
"fastapi>=0.115.2",
87+
"sse-starlette",
88+
"starlette",
8989
]
9090

9191
[[tool.uv.index]]

src/a2a/server/apps/jsonrpc/fastapi_app.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22

33
from typing import Any
44

5-
from a2a.server.apps.jsonrpc.fastapi_import_helpers import (
6-
FastAPI,
7-
Request,
8-
Response,
9-
)
5+
6+
try:
7+
from fastapi import FastAPI, Request, Response
8+
except ImportError:
9+
FastAPI = object
10+
Request = object
11+
Response = object
12+
1013
from a2a.server.apps.jsonrpc.jsonrpc_app import (
1114
CallContextBuilder,
1215
JSONRPCApplication,

src/a2a/server/apps/jsonrpc/fastapi_import_helpers.py

Lines changed: 0 additions & 32 deletions
This file was deleted.

src/a2a/server/apps/jsonrpc/jsonrpc_app.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
from a2a.auth.user import UnauthenticatedUser
1818
from a2a.auth.user import User as A2AUser
19-
from a2a.server.apps.jsonrpc.fastapi_import_helpers import FastAPI
2019
from a2a.server.context import ServerCallContext
2120
from a2a.server.request_handlers.jsonrpc_handler import JSONRPCHandler
2221
from a2a.server.request_handlers.request_handler import RequestHandler
@@ -45,6 +44,29 @@
4544

4645
logger = logging.getLogger(__name__)
4746

47+
try:
48+
from fastapi import FastAPI
49+
from sse_starlette.sse import EventSourceResponse
50+
from starlette.applications import Starlette
51+
from starlette.authentication import BaseUser
52+
from starlette.requests import Request
53+
from starlette.responses import JSONResponse, Response
54+
55+
_http_server_installed = True
56+
except ImportError:
57+
_http_server_installed = False
58+
# Define placeholder types for type hinting and to avoid import errors in other files.
59+
# These will not be used at runtime if deps are missing, as __init__ will raise.
60+
(
61+
FastAPI,
62+
EventSourceResponse,
63+
Starlette,
64+
BaseUser,
65+
Request,
66+
JSONResponse,
67+
Response,
68+
) = (object,) * 7
69+
4870

4971
class StarletteUserProxy(A2AUser):
5072
"""Adapts the Starlette User class to the A2A user representation."""
@@ -108,7 +130,7 @@ def __init__(
108130
extended_agent_card: AgentCard | None = None,
109131
context_builder: CallContextBuilder | None = None,
110132
):
111-
"""Initializes the A2AStarletteApplication.
133+
"""Initializes the JSONRPCApplication.
112134
113135
Args:
114136
agent_card: The AgentCard describing the agent's capabilities.
@@ -120,6 +142,10 @@ def __init__(
120142
ServerCallContext passed to the http_handler. If None, no
121143
ServerCallContext is passed.
122144
"""
145+
if not _http_server_installed:
146+
raise ImportError(
147+
'The `a2a-sdk[http-server]` package is required to use the `JSONRPCApplication`.'
148+
)
123149
self.agent_card = agent_card
124150
self.extended_agent_card = extended_agent_card
125151
self.handler = JSONRPCHandler(

src/a2a/server/apps/jsonrpc/starlette_app.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@
22

33
from typing import Any
44

5-
from starlette.applications import Starlette
6-
from starlette.routing import Route
5+
6+
try:
7+
from starlette.applications import Starlette
8+
from starlette.routing import Route
9+
except ImportError:
10+
Starlette = object
11+
Route = object
712

813
from a2a.server.apps.jsonrpc.jsonrpc_app import (
914
CallContextBuilder,

0 commit comments

Comments
 (0)