agentstack-sdk 0.6.0rc4__py3-none-any.whl → 0.6.1rc1__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.
@@ -8,6 +8,7 @@ from .file import *
8
8
  from .model_provider import *
9
9
  from .provider import *
10
10
  from .provider_build import *
11
+ from .provider_discovery import *
11
12
  from .user import *
12
13
  from .user_feedback import *
13
14
  from .vector_store import *
@@ -0,0 +1,57 @@
1
+ # Copyright 2025 © BeeAI a Series of LF Projects, LLC
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ from __future__ import annotations
4
+
5
+ from enum import StrEnum
6
+ from uuid import UUID
7
+
8
+ import pydantic
9
+ from a2a.types import AgentCard
10
+
11
+ from agentstack_sdk.platform.client import PlatformClient, get_platform_client
12
+
13
+
14
+ class DiscoveryState(StrEnum):
15
+ PENDING = "pending"
16
+ IN_PROGRESS = "in_progress"
17
+ COMPLETED = "completed"
18
+ FAILED = "failed"
19
+
20
+
21
+ class ProviderDiscovery(pydantic.BaseModel):
22
+ id: UUID
23
+ created_at: pydantic.AwareDatetime
24
+ status: DiscoveryState
25
+ docker_image: str
26
+ created_by: UUID
27
+ agent_card: AgentCard | None = None
28
+ error_message: str | None = None
29
+
30
+ @staticmethod
31
+ async def create(
32
+ *,
33
+ docker_image: str,
34
+ client: PlatformClient | None = None,
35
+ ) -> ProviderDiscovery:
36
+ async with client or get_platform_client() as client:
37
+ return pydantic.TypeAdapter(ProviderDiscovery).validate_python(
38
+ (
39
+ await client.post(
40
+ url="/api/v1/providers/discovery",
41
+ json={"docker_image": docker_image},
42
+ )
43
+ )
44
+ .raise_for_status()
45
+ .json()
46
+ )
47
+
48
+ async def get(self: ProviderDiscovery | str, *, client: PlatformClient | None = None) -> ProviderDiscovery:
49
+ discovery_id = self if isinstance(self, str) else str(self.id)
50
+ async with client or get_platform_client() as client:
51
+ result = pydantic.TypeAdapter(ProviderDiscovery).validate_json(
52
+ (await client.get(url=f"/api/v1/providers/discovery/{discovery_id}")).raise_for_status().content
53
+ )
54
+ if isinstance(self, ProviderDiscovery):
55
+ self.__dict__.update(result.__dict__)
56
+ return self
57
+ return result
@@ -18,8 +18,6 @@ from a2a.server.tasks import (
18
18
  from a2a.types import AgentInterface, TransportProtocol
19
19
  from fastapi import APIRouter, Depends, FastAPI
20
20
  from fastapi.applications import AppType
21
- from starlette.authentication import AuthenticationBackend
22
- from starlette.middleware.authentication import AuthenticationMiddleware
23
21
  from starlette.types import Lifespan
24
22
 
25
23
  from agentstack_sdk.server.agent import Agent, Executor
@@ -39,7 +37,6 @@ def create_app(
39
37
  dependencies: list[Depends] | None = None, # pyright: ignore [reportGeneralTypeIssues]
40
38
  override_interfaces: bool = True,
41
39
  task_timeout: timedelta = timedelta(minutes=10),
42
- auth_backend: AuthenticationBackend | None = None,
43
40
  **kwargs,
44
41
  ) -> FastAPI:
45
42
  queue_manager = queue_manager or InMemoryQueueManager()
@@ -78,10 +75,6 @@ def create_app(
78
75
  **kwargs,
79
76
  )
80
77
 
81
- if auth_backend:
82
- rest_app.add_middleware(AuthenticationMiddleware, backend=auth_backend)
83
- jsonrpc_app.add_middleware(AuthenticationMiddleware, backend=auth_backend)
84
-
85
78
  rest_app.mount("/jsonrpc", jsonrpc_app)
86
79
  rest_app.include_router(APIRouter(lifespan=lifespan))
87
80
  return rest_app
@@ -7,6 +7,7 @@ from datetime import timedelta
7
7
  from urllib.parse import urljoin
8
8
 
9
9
  from a2a.auth.user import User
10
+ from a2a.types import AgentCard, HTTPAuthSecurityScheme, SecurityScheme
10
11
  from async_lru import alru_cache
11
12
  from authlib.jose import JsonWebKey, JWTClaims, KeySet, jwt
12
13
  from authlib.jose.errors import JoseError
@@ -15,7 +16,6 @@ from fastapi.security import HTTPBearer
15
16
  from pydantic import Secret
16
17
  from starlette.authentication import (
17
18
  AuthCredentials,
18
- AuthenticationBackend,
19
19
  AuthenticationError,
20
20
  BaseUser,
21
21
  )
@@ -23,7 +23,7 @@ from starlette.requests import HTTPConnection
23
23
  from typing_extensions import override
24
24
 
25
25
  from agentstack_sdk.platform import use_platform_client
26
- from agentstack_sdk.types import JsonValue
26
+ from agentstack_sdk.types import JsonValue, SdkAuthenticationBackend
27
27
 
28
28
  logger = logging.getLogger(__name__)
29
29
 
@@ -70,7 +70,7 @@ async def discover_jwks() -> KeySet:
70
70
  raise RuntimeError(f"JWKS discovery failed for url {url}") from e
71
71
 
72
72
 
73
- class PlatformAuthBackend(AuthenticationBackend):
73
+ class PlatformAuthBackend(SdkAuthenticationBackend):
74
74
  def __init__(self, public_url: str | None = None, skip_audience_validation: bool | None = None) -> None:
75
75
  self.skip_audience_validation: bool = (
76
76
  skip_audience_validation
@@ -129,3 +129,16 @@ class PlatformAuthBackend(AuthenticationBackend):
129
129
  except Exception as e:
130
130
  logger.error(f"Authentication error: {e}")
131
131
  raise AuthenticationError(f"Authentication failed: {e}") from e
132
+
133
+ @override
134
+ def update_card_security_schemes(self, agent_card: AgentCard) -> None:
135
+ agent_card.security_schemes = {
136
+ "platform_context_token": SecurityScheme(
137
+ HTTPAuthSecurityScheme(
138
+ scheme="bearer",
139
+ bearer_format="JWT",
140
+ description="Platform context token, issued by the AgentStack server using POST /api/v1/context/{context_id}/token.",
141
+ )
142
+ ),
143
+ }
144
+ agent_card.security = [{"platform_context_token": []}]
@@ -24,7 +24,7 @@ from fastapi.applications import AppType
24
24
  from fastapi.responses import PlainTextResponse
25
25
  from httpx import HTTPError, HTTPStatusError
26
26
  from pydantic import AnyUrl
27
- from starlette.authentication import AuthenticationBackend, AuthenticationError
27
+ from starlette.authentication import AuthenticationError
28
28
  from starlette.middleware.authentication import AuthenticationMiddleware
29
29
  from starlette.requests import HTTPConnection
30
30
  from starlette.types import Lifespan
@@ -39,6 +39,7 @@ from agentstack_sdk.server.store.context_store import ContextStore
39
39
  from agentstack_sdk.server.store.memory_context_store import InMemoryContextStore
40
40
  from agentstack_sdk.server.telemetry import configure_telemetry as configure_telemetry_func
41
41
  from agentstack_sdk.server.utils import cancel_task
42
+ from agentstack_sdk.types import SdkAuthenticationBackend
42
43
  from agentstack_sdk.util.logging import configure_logger as configure_logger_func
43
44
  from agentstack_sdk.util.logging import logger
44
45
 
@@ -131,7 +132,7 @@ class Server:
131
132
  factory: bool = False,
132
133
  h11_max_incomplete_event_size: int | None = None,
133
134
  self_registration_client_factory: Callable[[], PlatformClient] | None = None,
134
- auth_backend: AuthenticationBackend | None = None,
135
+ auth_backend: SdkAuthenticationBackend | None = None,
135
136
  ) -> None:
136
137
  if self.server:
137
138
  raise RuntimeError("The server is already running")
@@ -201,9 +202,11 @@ class Server:
201
202
  push_sender=push_sender,
202
203
  task_timeout=task_timeout,
203
204
  request_context_builder=request_context_builder,
205
+ auth_backend=auth_backend,
204
206
  )
205
207
 
206
208
  if auth_backend:
209
+ auth_backend.update_card_security_schemes(self._agent.card)
207
210
 
208
211
  def on_error(connection: HTTPConnection, error: AuthenticationError) -> PlainTextResponse:
209
212
  return PlainTextResponse("Unauthorized", status_code=401)
agentstack_sdk/types.py CHANGED
@@ -1,8 +1,12 @@
1
1
  # Copyright 2025 © BeeAI a Series of LF Projects, LLC
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
 
4
+ import abc
4
5
  from typing import TYPE_CHECKING, TypeAlias
5
6
 
7
+ from a2a.types import AgentCard
8
+ from starlette.authentication import AuthenticationBackend
9
+
6
10
  if TYPE_CHECKING:
7
11
  JsonValue: TypeAlias = list["JsonValue"] | dict[str, "JsonValue"] | str | bool | int | float | None
8
12
  JsonDict: TypeAlias = dict[str, JsonValue]
@@ -13,3 +17,8 @@ else:
13
17
 
14
18
  JsonValue = TypeAliasType("JsonValue", "Union[dict[str, JsonValue], list[JsonValue], str, int, float, bool, None]") # noqa: UP007
15
19
  JsonDict = TypeAliasType("JsonDict", "dict[str, JsonValue]")
20
+
21
+
22
+ class SdkAuthenticationBackend(AuthenticationBackend, abc.ABC):
23
+ @abc.abstractmethod
24
+ def update_card_security_schemes(self, agent_card: AgentCard) -> None: ...
@@ -1,8 +1,8 @@
1
1
  # Copyright 2025 © BeeAI a Series of LF Projects, LLC
2
2
  # SPDX-License-Identifier: Apache-2.0
3
-
4
3
  import contextlib
5
4
  import contextvars
5
+ import re
6
6
  import typing
7
7
 
8
8
 
@@ -28,7 +28,14 @@ def resource_context(
28
28
  try:
29
29
  yield resource
30
30
  finally:
31
- contextvar.reset(token)
31
+ try:
32
+ contextvar.reset(token)
33
+ except ValueError as e:
34
+ if re.match(r"<Token var=.+ was created in a different Context", str(e)):
35
+ # Ignore contextvar reset errors when the contextvar was created in a different Context
36
+ pass
37
+ else:
38
+ raise
32
39
 
33
40
  return manager()
34
41
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: agentstack-sdk
3
- Version: 0.6.0rc4
3
+ Version: 0.6.1rc1
4
4
  Summary: Agent Stack SDK
5
5
  Author: IBM Corp.
6
6
  Requires-Dist: a2a-sdk==0.3.21
@@ -21,6 +21,7 @@ Requires-Dist: mcp>=1.12.3
21
21
  Requires-Dist: fastapi>=0.116.1
22
22
  Requires-Dist: authlib>=1.3.0
23
23
  Requires-Dist: async-lru>=2.0.4
24
+ Requires-Dist: cachetools>=6.2.3
24
25
  Requires-Python: >=3.11, <3.14
25
26
  Description-Content-Type: text/markdown
26
27
 
@@ -33,7 +33,7 @@ agentstack_sdk/a2a/extensions/ui/form_request.py,sha256=YeRiovV3EgqeBD8fHtu_b5qr
33
33
  agentstack_sdk/a2a/extensions/ui/settings.py,sha256=uZu_8u29gAu1H85twFb_LCRBO0jeaEiLgfamaFNUPGM,1814
34
34
  agentstack_sdk/a2a/extensions/ui/trajectory.py,sha256=G66rIpr2VTe1UvbK82EgLXwFtUC3QfbyN_uLQGUU8jA,2334
35
35
  agentstack_sdk/a2a/types.py,sha256=z1-OxRLIJgYDHwaBJ66MZNIqSTpE1zQ04BPGBGw9IC0,3582
36
- agentstack_sdk/platform/__init__.py,sha256=2yu0t7mtMPv14MWk1PFiU5t6xaZf9n4VhY6moKjdNFw,351
36
+ agentstack_sdk/platform/__init__.py,sha256=B7aJGw0_llNCHJJyP0tFTzt6fcw4JUM2vXjbRRTWrbQ,385
37
37
  agentstack_sdk/platform/client.py,sha256=KDN3R1wyoo-ZUYl6ArjRJxre0yAqB0Y6NyKrQpdI268,4234
38
38
  agentstack_sdk/platform/common.py,sha256=p6w4l49NaFp7LsjEBDAwghX6FliNChOeO7IHP_-TnXA,750
39
39
  agentstack_sdk/platform/configuration.py,sha256=YfOasb6LxE9LN6sMZPEU07Q61F7uIhiU3DIQFRaqinU,1690
@@ -43,6 +43,7 @@ agentstack_sdk/platform/file.py,sha256=lOqMwMKHKGWFy5P1huQ6DLRTiHU0KexX-s2qF3FIR
43
43
  agentstack_sdk/platform/model_provider.py,sha256=hv5UbFUFQ23IlalH5W-nCTvnUCrxBtZF4UrkeNWnwFE,4588
44
44
  agentstack_sdk/platform/provider.py,sha256=1juAfYc39sVwZ8ZbYz1ohVnzzRacJx6Junvo-7GgVmY,9071
45
45
  agentstack_sdk/platform/provider_build.py,sha256=Vn2XDdMGgQWvChWJmg9nxYFVecp42A1jXzURkFgSEQQ,7317
46
+ agentstack_sdk/platform/provider_discovery.py,sha256=mxf-8Rrjd6-r3M5L7-B9BWB8wwXOCzqzpo0cMMUH-3g,1865
46
47
  agentstack_sdk/platform/types.py,sha256=3OHERUoli6t9rlCiaZ2YfN26GXqMQzDFQx_UluCZVYA,1502
47
48
  agentstack_sdk/platform/user.py,sha256=pqkac4JZqagOYVvdm8mk48xHvVn6SPq2tbe5tXx_W4M,2090
48
49
  agentstack_sdk/platform/user_feedback.py,sha256=IfMzZsaFKpWCPz5MjppDsFLLMM-iVQUBGugz0_FmrqY,1305
@@ -51,27 +52,27 @@ agentstack_sdk/platform/vector_store.py,sha256=h98RKGuN1SvmfL_bxf3WCLvY1IeQ00Wf7
51
52
  agentstack_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
53
  agentstack_sdk/server/__init__.py,sha256=vc06L5ILofytmLJC9hJUzA9LakUYUNYGiBoSXNs9hQc,152
53
54
  agentstack_sdk/server/agent.py,sha256=tprDvYwsSoImJkMCMVvHKzacH2pWtQUWu19qgWAyNMk,29170
54
- agentstack_sdk/server/app.py,sha256=1-g_6FBU4lnrBI2KZVnTvsfdKrHyChkeYmJ01iIrj4Y,3396
55
+ agentstack_sdk/server/app.py,sha256=pLyf4CyG8PWYuNDUO0FE99XyDjjc9HFj8ii3PrWDGd8,3024
55
56
  agentstack_sdk/server/constants.py,sha256=huQAP351AeNt536tB-axJSseHMHfyDKwJdlackjLGnw,188
56
57
  agentstack_sdk/server/context.py,sha256=yBAk3RgBsat1nULzFs2OvF2UKKeNAT8yaSN_s-bcPTU,2712
57
58
  agentstack_sdk/server/dependencies.py,sha256=kyUwrIJe99n7UQmqGn_bo--YkPiAR6S9SoeOBwaeW68,5022
58
59
  agentstack_sdk/server/exceptions.py,sha256=jr8otByt8HFY9OWptuWdpq4WHE7A1srCSRXZV066FrI,94
59
60
  agentstack_sdk/server/middleware/__init__.py,sha256=pEJG3OupRq7IF3O70g2pvDU_EmDF0D3iAuGWXB-_Ipk,94
60
- agentstack_sdk/server/middleware/platform_auth_backend.py,sha256=h2P4jKJpXOmie1tFU2E5YW-c6-BksINmWEonNUQ5l3g,4986
61
- agentstack_sdk/server/server.py,sha256=twD5j4Re8rfg63CjcMLJg_tpPBKAkffnP22hTkVS5iY,15909
61
+ agentstack_sdk/server/middleware/platform_auth_backend.py,sha256=fhSWM3Oj794qwRoKcCnAm6fFz8icjK2Ibg8qyCKaWHM,5606
62
+ agentstack_sdk/server/server.py,sha256=OOEsBB_g5l4ALEepaK5ZZjtyYV65Kv_oLFBnPBZTLVs,16058
62
63
  agentstack_sdk/server/store/__init__.py,sha256=jr8otByt8HFY9OWptuWdpq4WHE7A1srCSRXZV066FrI,94
63
64
  agentstack_sdk/server/store/context_store.py,sha256=ZzXSlxaV_xaTEVDAO0oC0eCiNQve2ydjYUJK3oUAOXA,1060
64
65
  agentstack_sdk/server/store/memory_context_store.py,sha256=S604ATyk9wA2D_pZL-Q-I4x01mItKihLJmGwp7bumC4,2346
65
66
  agentstack_sdk/server/store/platform_context_store.py,sha256=bv5-sVJUVVblYIAjLsl0_VOqstjfAXWuQgWhewE_9OI,2614
66
67
  agentstack_sdk/server/telemetry.py,sha256=MJ5JGF3L_ef8eqx-yguJHgIhbpDtHRSfKm2QKFtlHmI,2014
67
68
  agentstack_sdk/server/utils.py,sha256=0s7N-kWEWnPuI2Ki4PZuX5uY48KFLCOHg-lnxRDVEg8,917
68
- agentstack_sdk/types.py,sha256=1GOt-l2xnJTS_6u37YNoMXkuckX2XwjQ1aH1iv6QRIQ,593
69
+ agentstack_sdk/types.py,sha256=VTOV489DavWGT1qS5iDCSwY4lxa3PEFODeFk19OYHSw,865
69
70
  agentstack_sdk/util/__init__.py,sha256=dCOBqJYOJYvvQSjDZysZGkLxvZV-o9j367ze3jnX_Rc,126
70
71
  agentstack_sdk/util/file.py,sha256=rm5b47tHTmJBsHlqGcUqFCP0Bz5HKXPHWW_h-IpG9pw,9035
71
72
  agentstack_sdk/util/httpx.py,sha256=g6WKgkGCLc40wZA2CPYO_R2P-nav6QP1XmVlgkh9wYY,491
72
73
  agentstack_sdk/util/logging.py,sha256=hGLkjw-P3GefiUQmDmcz7BZQxfT2Y44XlLyAMNxZXMo,2136
73
- agentstack_sdk/util/resource_context.py,sha256=OmjEXvrLQA6nBkVSBt0n24hNNxJkucd-N32haxJ4Mno,1093
74
+ agentstack_sdk/util/resource_context.py,sha256=AMvTxcG8zdMZplzFACFvgOgARp3xP9BQqz6eh0EyLqg,1458
74
75
  agentstack_sdk/util/utils.py,sha256=18qFqMRkX4g4eIpvIvLb4FZAs8Q8ojJrpm19oJleb-k,1593
75
- agentstack_sdk-0.6.0rc4.dist-info/WHEEL,sha256=M6du7VZflc4UPsGphmOXHANdgk8zessdJG0DBUuoA-U,78
76
- agentstack_sdk-0.6.0rc4.dist-info/METADATA,sha256=Ooq2LT9oNUCsmUZ7JE5gKg53fOcexsJbGdM68aRV6WQ,4433
77
- agentstack_sdk-0.6.0rc4.dist-info/RECORD,,
76
+ agentstack_sdk-0.6.1rc1.dist-info/WHEEL,sha256=M6du7VZflc4UPsGphmOXHANdgk8zessdJG0DBUuoA-U,78
77
+ agentstack_sdk-0.6.1rc1.dist-info/METADATA,sha256=gVOcXRyRSsmet1fMR4DnJNoTD7OYpjMdC3QjqmbAEZ4,4466
78
+ agentstack_sdk-0.6.1rc1.dist-info/RECORD,,