acp-sdk 0.12.3__py3-none-any.whl → 1.0.0__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.
@@ -0,0 +1,5 @@
1
+ from pydantic import BaseModel, ConfigDict
2
+
3
+
4
+ class AnyModel(BaseModel):
5
+ model_config = ConfigDict(extra="allow")
acp_sdk/models/errors.py CHANGED
@@ -1,7 +1,10 @@
1
1
  from enum import Enum
2
+ from typing import Optional
2
3
 
3
4
  from pydantic import BaseModel
4
5
 
6
+ from acp_sdk.models.common import AnyModel
7
+
5
8
 
6
9
  class ErrorCode(str, Enum):
7
10
  SERVER_ERROR = "server_error"
@@ -10,8 +13,9 @@ class ErrorCode(str, Enum):
10
13
 
11
14
 
12
15
  class Error(BaseModel):
13
- code: ErrorCode
16
+ code: ErrorCode | str # Allow arbitrary string for backwards compatibility
14
17
  message: str
18
+ data: Optional[AnyModel] = None
15
19
 
16
20
 
17
21
  class ACPError(Exception):
acp_sdk/models/models.py CHANGED
@@ -8,16 +8,13 @@ from typing import Any, Literal, Optional, Union
8
8
  from pydantic import AnyUrl, BaseModel, ConfigDict, Field
9
9
  from pydantic.json_schema import SkipJsonSchema
10
10
 
11
+ from acp_sdk.models.common import AnyModel
11
12
  from acp_sdk.models.errors import ACPError, Error
12
13
  from acp_sdk.models.platform import PlatformUIAnnotation
13
14
  from acp_sdk.models.types import AgentName, ResourceUrl, RunId, SessionId
14
15
  from acp_sdk.shared import ResourceLoader, ResourceStore
15
16
 
16
17
 
17
- class AnyModel(BaseModel):
18
- model_config = ConfigDict(extra="allow")
19
-
20
-
21
18
  class Author(BaseModel):
22
19
  name: str
23
20
  email: str | None = None
@@ -111,11 +108,38 @@ class CitationMetadata(BaseModel):
111
108
  """
112
109
 
113
110
  kind: Literal["citation"] = "citation"
114
- start_index: Optional[int]
115
- end_index: Optional[int]
116
- url: Optional[str]
117
- title: Optional[str]
118
- description: Optional[str]
111
+ start_index: Optional[int] = None
112
+ end_index: Optional[int] = None
113
+ url: Optional[str] = None
114
+ title: Optional[str] = None
115
+ description: Optional[str] = None
116
+
117
+
118
+ class TrajectoryMetadata(BaseModel):
119
+ """
120
+ Represents trajectory information for an agent's reasoning or tool execution
121
+ steps. This metadata helps track the agent's decision-making process and
122
+ provides transparency into how the agent arrived at its response.
123
+
124
+ TrajectoryMetadata can capture either:
125
+ 1. A reasoning step with a message
126
+ 2. A tool execution with tool name, input, and output
127
+
128
+ This information can be used for debugging, audit trails, and providing
129
+ users with insight into the agent's thought process.
130
+
131
+ Properties:
132
+ - message: A reasoning step or thought in the agent's decision process.
133
+ - tool_name: Name of the tool that was executed.
134
+ - tool_input: Input parameters passed to the tool.
135
+ - tool_output: Output or result returned by the tool.
136
+ """
137
+
138
+ kind: Literal["trajectory"] = "trajectory"
139
+ message: Optional[str] = None
140
+ tool_name: Optional[str] = None
141
+ tool_input: Optional[AnyModel] = None
142
+ tool_output: Optional[AnyModel] = None
119
143
 
120
144
 
121
145
  class MessagePart(BaseModel):
@@ -127,7 +151,7 @@ class MessagePart(BaseModel):
127
151
 
128
152
  model_config = ConfigDict(extra="allow")
129
153
 
130
- metadata: Optional[CitationMetadata] = Field(discriminator="kind", default=None)
154
+ metadata: Optional[CitationMetadata | TrajectoryMetadata] = Field(discriminator="kind", default=None)
131
155
 
132
156
  def model_post_init(self, __context: Any) -> None:
133
157
  if self.content is not None and self.content_url is not None:
@@ -326,10 +350,20 @@ Event = Union[
326
350
  ]
327
351
 
328
352
 
353
+ class InputContentTypes(BaseModel):
354
+ types: list[str]
355
+
356
+
357
+ class OutputContentTypes(BaseModel):
358
+ types: list[str]
359
+
360
+
329
361
  class AgentManifest(BaseModel):
330
362
  name: str
331
363
  description: str | None = None
332
364
  metadata: Metadata = Metadata()
365
+ input_content_types: list[str] = Field(default_factory=lambda: ["*/*"])
366
+ output_content_types: list[str] = Field(default_factory=lambda: ["*/*"])
333
367
 
334
368
 
335
369
  class Session(BaseModel):
acp_sdk/server/agent.py CHANGED
@@ -17,6 +17,14 @@ class AgentManifest(abc.ABC):
17
17
  def description(self) -> str:
18
18
  return ""
19
19
 
20
+ @property
21
+ def input_content_types(self) -> list[str]:
22
+ return []
23
+
24
+ @property
25
+ def output_content_types(self) -> list[str]:
26
+ return []
27
+
20
28
  @property
21
29
  def metadata(self) -> Metadata:
22
30
  return Metadata()
@@ -38,6 +46,8 @@ def agent(
38
46
  description: str | None = None,
39
47
  *,
40
48
  metadata: Metadata | None = None,
49
+ input_content_types: list[str] | None = None,
50
+ output_content_types: list[str] | None = None,
41
51
  ) -> Callable[[Callable], AgentManifest]:
42
52
  """Decorator to create an agent."""
43
53
 
@@ -67,6 +77,14 @@ def agent(
67
77
  def metadata(self) -> Metadata:
68
78
  return metadata or Metadata()
69
79
 
80
+ @property
81
+ def input_content_types(self) -> list[str]:
82
+ return input_content_types or ["*/*"]
83
+
84
+ @property
85
+ def output_content_types(self) -> list[str]:
86
+ return output_content_types or ["*/*"]
87
+
70
88
  agent: AgentManifest
71
89
  if inspect.isasyncgenfunction(fn):
72
90
 
acp_sdk/server/app.py CHANGED
@@ -13,6 +13,7 @@ from fastapi.encoders import jsonable_encoder
13
13
  from fastapi.middleware.cors import CORSMiddleware
14
14
  from fastapi.responses import JSONResponse, StreamingResponse
15
15
  from obstore.exceptions import NotFoundError
16
+ from pydantic import AnyHttpUrl, ValidationError
16
17
 
17
18
  from acp_sdk.models import (
18
19
  ACPError,
@@ -67,6 +68,7 @@ def create_app(
67
68
  resource_store: ResourceStore | None = None,
68
69
  resource_loader: ResourceLoader | None = None,
69
70
  forward_resources: bool = True,
71
+ forward_base_url: AnyHttpUrl | str | None = None,
70
72
  lifespan: Lifespan[AppType] | None = None,
71
73
  dependencies: list[Depends] | None = None,
72
74
  ) -> FastAPI:
@@ -76,6 +78,12 @@ def create_app(
76
78
  ):
77
79
  raise ValueError("Resource forwarding must be enabled when resource store does not support HTTP URLs")
78
80
 
81
+ if isinstance(forward_base_url, str):
82
+ try:
83
+ forward_base_url = AnyHttpUrl(forward_base_url)
84
+ except ValidationError:
85
+ raise ValueError("forward_base_url must be a valid http(s) url")
86
+
79
87
  executor: ThreadPoolExecutor
80
88
  client = httpx.AsyncClient()
81
89
 
@@ -141,7 +149,13 @@ def create_app(
141
149
  async def list_agents() -> AgentsListResponse:
142
150
  return AgentsListResponse(
143
151
  agents=[
144
- AgentModel(name=agent.name, description=agent.description, metadata=agent.metadata)
152
+ AgentModel(
153
+ name=agent.name,
154
+ description=agent.description,
155
+ metadata=agent.metadata,
156
+ input_content_types=agent.input_content_types,
157
+ output_content_types=agent.output_content_types,
158
+ )
145
159
  for agent in agents.values()
146
160
  ]
147
161
  )
@@ -149,7 +163,13 @@ def create_app(
149
163
  @app.get("/agents/{name}")
150
164
  async def read_agent(name: AgentName) -> AgentReadResponse:
151
165
  agent = find_agent(name)
152
- return AgentModel(name=agent.name, description=agent.description, metadata=agent.metadata)
166
+ return AgentModel(
167
+ name=agent.name,
168
+ description=agent.description,
169
+ metadata=agent.metadata,
170
+ input_content_types=agent.input_content_types,
171
+ output_content_types=agent.output_content_types,
172
+ )
153
173
 
154
174
  @app.get("/ping")
155
175
  async def ping() -> PingResponse:
@@ -165,6 +185,10 @@ def create_app(
165
185
  def create_resource_url_forwarded(id: ResourceId) -> ResourceUrl:
166
186
  if not forward_resources:
167
187
  raise RuntimeError("Resource forwarding disabled")
188
+ if forward_base_url:
189
+ return ResourceUrl(
190
+ url=str(app.url_path_for("get_resource", resource_id=id).make_absolute_url(str(forward_base_url)))
191
+ )
168
192
  return ResourceUrl(url=str(req.url_for("get_resource", resource_id=id)))
169
193
 
170
194
  async def create_resource_url(id: ResourceId) -> ResourceUrl:
acp_sdk/server/server.py CHANGED
@@ -9,6 +9,7 @@ import requests
9
9
  import uvicorn
10
10
  import uvicorn.config
11
11
  from fastapi import FastAPI
12
+ from pydantic import AnyHttpUrl
12
13
 
13
14
  from acp_sdk.models import Metadata
14
15
  from acp_sdk.server.agent import AgentManifest
@@ -31,13 +32,21 @@ class Server:
31
32
  self,
32
33
  name: str | None = None,
33
34
  description: str | None = None,
35
+ input_content_types: list[str] | None = None,
36
+ output_content_types: list[str] | None = None,
34
37
  *,
35
38
  metadata: Metadata | None = None,
36
39
  ) -> Callable:
37
40
  """Decorator to register an agent."""
38
41
 
39
42
  def decorator(fn: Callable) -> Callable:
40
- agent = agent_decorator(name=name, description=description, metadata=metadata)(fn)
43
+ agent = agent_decorator(
44
+ name=name,
45
+ description=description,
46
+ metadata=metadata,
47
+ input_content_types=input_content_types,
48
+ output_content_types=output_content_types,
49
+ )(fn)
41
50
  self.register(agent)
42
51
  return fn
43
52
 
@@ -59,6 +68,8 @@ class Server:
59
68
  store: Store | None = None,
60
69
  resource_store: ResourceStore | None = None,
61
70
  resource_loader: ResourceLoader | None = None,
71
+ forward_resources: bool = True,
72
+ forward_base_url: AnyHttpUrl | str | None = None,
62
73
  host: str = "127.0.0.1",
63
74
  port: int = 8000,
64
75
  uds: str | None = None,
@@ -127,6 +138,8 @@ class Server:
127
138
  store=store,
128
139
  resource_loader=resource_loader,
129
140
  resource_store=resource_store,
141
+ forward_resources=forward_resources,
142
+ forward_base_url=forward_base_url,
130
143
  )
131
144
 
132
145
  if configure_logger:
@@ -196,6 +209,8 @@ class Server:
196
209
  store: Store | None = None,
197
210
  resource_store: ResourceStore | None = None,
198
211
  resource_loader: ResourceLoader | None = None,
212
+ forward_resources: bool = True,
213
+ forward_base_url: AnyHttpUrl | str | None = None,
199
214
  host: str = "127.0.0.1",
200
215
  port: int = 8000,
201
216
  uds: str | None = None,
@@ -256,6 +271,8 @@ class Server:
256
271
  store=store,
257
272
  resource_store=resource_store,
258
273
  resource_loader=resource_loader,
274
+ forward_resources=forward_resources,
275
+ forward_base_url=forward_base_url,
259
276
  host=host,
260
277
  port=port,
261
278
  uds=uds,
@@ -331,14 +348,14 @@ class Server:
331
348
  request_data = {
332
349
  "location": f"http://{host}:{self.server.config.port}",
333
350
  }
334
- await async_request_with_retry(lambda client, data=request_data: client.get(f"{url}/api/v1/providers"))
335
351
  try:
352
+ await async_request_with_retry(lambda client, data=request_data: client.get(f"{url}/api/v1/providers"))
336
353
  await async_request_with_retry(
337
354
  lambda client, data=request_data: client.post(
338
355
  f"{url}/api/v1/providers", json=data, params={"auto_remove": True}
339
356
  )
340
357
  )
341
- logger.info("Agent registered to the beeai server.")
358
+ logger.debug("Agent registered to the beeai server.")
342
359
 
343
360
  # check missing env keyes
344
361
  envs_request = await async_request_with_retry(lambda client: client.get(f"{url}/api/v1/variables"))
@@ -361,17 +378,17 @@ class Server:
361
378
  elif env.get("required"):
362
379
  missing_keyes.append(env)
363
380
  if len(missing_keyes):
364
- logger.error(f"Can not run agent, missing required env variables: {missing_keyes}")
381
+ logger.debug(f"Can not run agent, missing required env variables: {missing_keyes}")
365
382
  raise Exception("Missing env variables")
366
383
 
367
384
  except requests.exceptions.ConnectionError as e:
368
- logger.warning(f"Can not reach server, check if running on {url} : {e}")
385
+ logger.debug(f"Can not reach server, check if running on {url} : {e}")
369
386
  except (requests.exceptions.HTTPError, Exception) as e:
370
387
  try:
371
388
  error_message = e.response.json().get("detail")
372
389
  if error_message:
373
- logger.warning(f"Agent can not be registered to beeai server: {error_message}")
390
+ logger.debug(f"Agent can not be registered to beeai server: {error_message}")
374
391
  else:
375
- logger.warning(f"Agent can not be registered to beeai server: {e}")
392
+ logger.debug(f"Agent can not be registered to beeai server: {e}")
376
393
  except Exception:
377
- logger.warning(f"Agent can not be registered to beeai server: {e}")
394
+ logger.debug(f"Agent can not be registered to beeai server: {e}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: acp-sdk
3
- Version: 0.12.3
3
+ Version: 1.0.0
4
4
  Summary: Agent Communication Protocol SDK
5
5
  Author: IBM Corp.
6
6
  Maintainer-email: Tomas Pilar <thomas7pilar@gmail.com>
@@ -7,20 +7,21 @@ acp_sdk/client/client.py,sha256=3lQ0URQK2q6_QuADMhbbEijrWegaFRtAvfPDs2XnMS8,1259
7
7
  acp_sdk/client/types.py,sha256=_H6zYt-2OHOOYRtssRnbDIiwmgsl2-KIXc9lb-mJLFA,133
8
8
  acp_sdk/client/utils.py,sha256=2jhJyrPJmVFRoDJh0q_JMqOMlC3IxCh-6HXed-PIZS8,924
9
9
  acp_sdk/models/__init__.py,sha256=_XDSvUwlHeRsqUayAxHusJ5s8Z1jWXV1ZcUKlJakOt4,200
10
- acp_sdk/models/errors.py,sha256=rEyaMVvQuBi7fwWe_d0PGGySYsD3FZTluQ-SkC0yhAs,444
11
- acp_sdk/models/models.py,sha256=cSVVmj8tl1CuHUVK_sq7Fcnw8s-XEaOBCWlQTIf_7lo,10889
10
+ acp_sdk/models/common.py,sha256=Rb22TZCTs_cjTSZ1ti0qBHBNh1yH7VL94fIaYwliAYU,117
11
+ acp_sdk/models/errors.py,sha256=r-blfUHLs4OO9twop_Iavb3O_Y3mj18fYBQHGLZiLT0,612
12
+ acp_sdk/models/models.py,sha256=J47J4Az40mnGreiZRCD17gb8QjvOEfY2iuD4jdETaOc,12206
12
13
  acp_sdk/models/platform.py,sha256=qgQhBZZNPG9XLlytEZmuv1LTkejbklmlj7YpnpUV_DE,497
13
14
  acp_sdk/models/schemas.py,sha256=Vu3aO-6M0IW71I9thxAiphLGXXMvyZXFMJCdj7euUmc,915
14
15
  acp_sdk/models/types.py,sha256=tH79qqpW3DrPJggZD1KFlLtGE_ZKT6eLtwiR3p3x2QM,145
15
16
  acp_sdk/server/__init__.py,sha256=TfTOOI7G2nejjOB6RZB5ujynyh3bFeH51pfDIMzv3N4,627
16
- acp_sdk/server/agent.py,sha256=tzdk9bXb4aKBKD3F1-QfI7zrjMZYEg6qm3gGRWJGC1E,3739
17
- acp_sdk/server/app.py,sha256=dugceYPELl6N1_OQQ6JP5VCfVSm0rcanFtjDpscOy6o,11586
17
+ acp_sdk/server/agent.py,sha256=T43TuYT4iVzfnxytvF1CbolLC_KoSRnITogmGWaRabs,4271
18
+ acp_sdk/server/app.py,sha256=SYjpo6gVJXkTpnQ70lYjLLXz23nIOQAT6X4n2QWZhUw,12502
18
19
  acp_sdk/server/context.py,sha256=Xz1am_HLNTgEvG0IPtS0tRJcPk-rEhLtNyTQGUAvLQw,1271
19
20
  acp_sdk/server/errors.py,sha256=GSO8yYIqEeX8Y4Lz86ks35dMTHiQiXuOrLYYx0eXsbI,2110
20
21
  acp_sdk/server/executor.py,sha256=ktM1FCwixtbjsU60VM7PHxwF_Saz15M_9fNXN4mItrU,12607
21
22
  acp_sdk/server/logging.py,sha256=Oc8yZigCsuDnHHPsarRzu0RX3NKaLEgpELM2yovGKDI,411
22
23
  acp_sdk/server/resources.py,sha256=g9C2Xr_SyvAFsV1uHQLEe1H7CgLIjfQZ51Nj3n-w0f4,1174
23
- acp_sdk/server/server.py,sha256=HJOub1ynHiJTQrfKq_bq0r9aqgL1kQeboZH_ArZcuh0,14651
24
+ acp_sdk/server/server.py,sha256=cnFAquwNvFnHQTzH20ZOJcwcTJFtgK78-uEthZJw0zc,15364
24
25
  acp_sdk/server/telemetry.py,sha256=lbB2ppijUcqbHUOn0e-15LGcVvT_qrMguq8qBokICac,2016
25
26
  acp_sdk/server/types.py,sha256=gLb5wCkMYhmu2laj_ymK-TPfN9LSjRgKOP1H_893UzA,304
26
27
  acp_sdk/server/utils.py,sha256=O9GUZ8SKqk8P5Vo-N4BD7hXS3XuE7l8wifOhvKMX3ws,2715
@@ -32,6 +33,6 @@ acp_sdk/server/store/store.py,sha256=jGmYy9oiuVjhYYJY8QRo4g2J2Qyt1HLTmq_eHy4aI7c
32
33
  acp_sdk/server/store/utils.py,sha256=JumEOMs1h1uGlnHnUGeguee-srGzT7_Y2NVEYt01QuY,92
33
34
  acp_sdk/shared/__init__.py,sha256=vZuhdQ6lrWVdyYPmIyXpPvs5eMnzemhNek3gfYPA3Bc,138
34
35
  acp_sdk/shared/resources.py,sha256=3oPvevYv2B1YaHyoMH85B7fcHVyhgZDUaDCBVEflTlA,1592
35
- acp_sdk-0.12.3.dist-info/METADATA,sha256=RglEI7Eje0tSG0-insJiq7ZNwpnvrgm18FlRSRIUng8,1713
36
- acp_sdk-0.12.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
37
- acp_sdk-0.12.3.dist-info/RECORD,,
36
+ acp_sdk-1.0.0.dist-info/METADATA,sha256=Tez7d-Zl2X_j5oXqVCil6kUZdaIO_BWOep_LPbaPF6g,1712
37
+ acp_sdk-1.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
38
+ acp_sdk-1.0.0.dist-info/RECORD,,