agenta 0.68.0__py3-none-any.whl → 0.72.4__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.
agenta/__init__.py CHANGED
@@ -1,52 +1,50 @@
1
1
  from typing import Any, Callable, Optional
2
2
 
3
- from .sdk.utils.preinit import PreInitObject
4
-
5
- from agenta.client import AgentaApi, AsyncAgentaApi
6
3
  import agenta.client.backend.types as client_types # pylint: disable=wrong-import-order
4
+ from agenta.client import AgentaApi, AsyncAgentaApi
7
5
 
8
- from .sdk.types import (
9
- MCField,
10
- DictInput,
11
- MultipleChoice,
12
- FloatParam,
13
- IntParam,
14
- MultipleChoiceParam,
15
- GroupedMultipleChoiceParam,
16
- MessagesInput,
17
- TextParam,
18
- FileInputURL,
19
- BinaryParam,
20
- Prompt,
21
- PromptTemplate,
22
- )
6
+ from .sdk import assets as assets
23
7
 
24
- from .sdk.agenta_init import Config, AgentaSingleton, init as _init
25
- from .sdk.utils.logging import get_module_logger
26
- from .sdk.utils.costs import calculate_token_usage
27
- from .sdk.tracing import Tracing, get_tracer
28
- from .sdk.tracing.conventions import Reference
29
- from .sdk.decorators.tracing import instrument
8
+ # evaluations
9
+ from .sdk import testsets as testsets
10
+ from .sdk import tracer
11
+ from .sdk.agenta_init import AgentaSingleton, Config
12
+ from .sdk.agenta_init import init as _init
13
+ from .sdk.context.running import workflow_mode_enabled
30
14
  from .sdk.decorators.running import (
31
- workflow,
32
15
  application,
33
16
  evaluator,
17
+ workflow,
34
18
  )
35
- from .sdk.decorators.serving import route, app
36
- from .sdk.context.running import workflow_mode_enabled
19
+ from .sdk.decorators.serving import app, route
20
+ from .sdk.decorators.tracing import instrument
37
21
  from .sdk.litellm import litellm as callbacks
38
22
  from .sdk.managers.apps import AppManager
39
- from .sdk.managers.vault import VaultManager
40
- from .sdk.managers.secrets import SecretsManager
41
23
  from .sdk.managers.config import ConfigManager
42
- from .sdk.managers.variant import VariantManager
43
24
  from .sdk.managers.deployment import DeploymentManager
44
- from .sdk import assets as assets
45
- from .sdk import tracer
46
-
47
- # evaluations
48
- from .sdk import testsets as testsets
49
-
25
+ from .sdk.managers.secrets import SecretsManager
26
+ from .sdk.managers.variant import VariantManager
27
+ from .sdk.managers.vault import VaultManager
28
+ from .sdk.tracing import Tracing, get_tracer
29
+ from .sdk.tracing.conventions import Reference
30
+ from .sdk.types import (
31
+ BinaryParam,
32
+ DictInput,
33
+ FileInputURL,
34
+ FloatParam,
35
+ GroupedMultipleChoiceParam,
36
+ IntParam,
37
+ MCField,
38
+ MessagesInput,
39
+ MultipleChoice,
40
+ MultipleChoiceParam,
41
+ Prompt,
42
+ PromptTemplate,
43
+ TextParam,
44
+ )
45
+ from .sdk.utils.costs import calculate_token_usage
46
+ from .sdk.utils.logging import get_module_logger
47
+ from .sdk.utils.preinit import PreInitObject
50
48
 
51
49
  config = PreInitObject("agenta.config", Config)
52
50
  DEFAULT_AGENTA_SINGLETON_INSTANCE = AgentaSingleton()
@@ -88,3 +86,35 @@ def init(
88
86
 
89
87
  tracing = DEFAULT_AGENTA_SINGLETON_INSTANCE.tracing # type: ignore
90
88
  tracer = get_tracer(tracing)
89
+
90
+
91
+ def get_trace_url(trace_id: Optional[str] = None) -> str:
92
+ """
93
+ Build a URL to view the current trace in the Agenta UI.
94
+
95
+ Automatically extracts the trace ID from the current tracing context.
96
+ Can also accept an explicit trace_id if needed.
97
+
98
+ Args:
99
+ trace_id: Optional trace ID (hex string format). If not provided,
100
+ it will be automatically extracted from the current trace context.
101
+
102
+ Returns:
103
+ The full URL to view the trace in the observability dashboard
104
+
105
+ Raises:
106
+ RuntimeError: If the SDK is not initialized, no active trace context exists,
107
+ or scope info cannot be fetched
108
+
109
+ Example:
110
+ >>> import agenta as ag
111
+ >>> ag.init(api_key="xxx")
112
+ >>>
113
+ >>> @ag.instrument()
114
+ >>> def my_function():
115
+ >>> # Get URL for the current trace
116
+ >>> url = ag.tracing.get_trace_url()
117
+ >>> print(url)
118
+ >>> return "result"
119
+ """
120
+ return DEFAULT_AGENTA_SINGLETON_INSTANCE.tracing.get_trace_url(trace_id)
agenta/sdk/agenta_init.py CHANGED
@@ -1,16 +1,15 @@
1
- import toml
2
- from os import getenv
3
- from typing import Optional, Callable, Any
4
1
  from importlib.metadata import version
2
+ from os import getenv
3
+ from typing import Any, Callable, Optional
5
4
 
6
- from agenta.sdk.utils.helpers import parse_url
7
- from agenta.sdk.utils.globals import set_global
8
- from agenta.sdk.utils.logging import get_module_logger
5
+ import requests
6
+ import toml
9
7
  from agenta.client.client import AgentaApi, AsyncAgentaApi
10
-
11
- from agenta.sdk.tracing import Tracing
12
8
  from agenta.sdk.contexts.routing import RoutingContext
13
-
9
+ from agenta.sdk.tracing import Tracing
10
+ from agenta.sdk.utils.globals import set_global
11
+ from agenta.sdk.utils.helpers import parse_url
12
+ from agenta.sdk.utils.logging import get_module_logger
14
13
 
15
14
  log = get_module_logger(__name__)
16
15
 
@@ -19,6 +18,7 @@ class AgentaSingleton:
19
18
  """Singleton class to save all the "global variables" for the sdk."""
20
19
 
21
20
  _instance = None
21
+ _initialized = False
22
22
  config = None
23
23
  tracing = None
24
24
 
@@ -26,6 +26,11 @@ class AgentaSingleton:
26
26
  async_api = None
27
27
 
28
28
  def __init__(self):
29
+ # Only initialize once
30
+ if AgentaSingleton._initialized:
31
+ return
32
+
33
+ AgentaSingleton._initialized = True
29
34
  self.host = None
30
35
  self.api_url = None
31
36
  self.api_key = None
@@ -33,6 +38,11 @@ class AgentaSingleton:
33
38
  self.scope_type = None
34
39
  self.scope_id = None
35
40
 
41
+ # Cached scope information for URL building
42
+ self.organization_id: Optional[str] = None
43
+ self.workspace_id: Optional[str] = None
44
+ self.project_id: Optional[str] = None
45
+
36
46
  def __new__(cls):
37
47
  if not cls._instance:
38
48
  cls._instance = super(AgentaSingleton, cls).__new__(cls)
@@ -70,6 +80,10 @@ class AgentaSingleton:
70
80
 
71
81
  """
72
82
 
83
+ # Idempotency check: if already initialized, skip re-initialization
84
+ if self.tracing and self.api and self.async_api:
85
+ return
86
+
73
87
  log.info("Agenta - SDK ver: %s", version("agenta"))
74
88
 
75
89
  config = {}
@@ -100,7 +114,7 @@ class AgentaSingleton:
100
114
 
101
115
  try:
102
116
  assert _api_url and isinstance(_api_url, str), (
103
- "API URL is required. Please provide a valid API URL or set AGENTA_API_URL environment variable."
117
+ "API URL is required. Please set AGENTA_API_URL environment variable or pass api_url parameter in ag.init()."
104
118
  )
105
119
  self.host = _host
106
120
  self.api_url = _api_url
@@ -118,6 +132,11 @@ class AgentaSingleton:
118
132
  or None # NO FALLBACK
119
133
  )
120
134
 
135
+ if self.api_key is None:
136
+ log.error(
137
+ "API key is required. Please set AGENTA_API_KEY environment variable or pass api_key parameter in ag.init()."
138
+ )
139
+
121
140
  log.info("Agenta - API URL: %s", self.api_url)
122
141
 
123
142
  self.scope_type = (
@@ -159,6 +178,65 @@ class AgentaSingleton:
159
178
  api_key=self.api_key,
160
179
  )
161
180
 
181
+ # Reset cached scope info on re-init
182
+ self.organization_id = None
183
+ self.workspace_id = None
184
+ self.project_id = None
185
+
186
+ def resolve_scopes(self) -> Optional[tuple[str, str, str]]:
187
+ """Fetch and cache workspace_id and project_id from the API."""
188
+ if (
189
+ self.organization_id is not None
190
+ and self.workspace_id is not None
191
+ and self.project_id is not None
192
+ ):
193
+ return
194
+
195
+ if self.api_url is None or self.api_key is None:
196
+ log.error("API URL or API key is not set. Please call ag.init() first.")
197
+ return
198
+
199
+ try:
200
+ response = requests.get(
201
+ f"{self.api_url}/projects/current",
202
+ headers={"Authorization": f"ApiKey {self.api_key}"},
203
+ timeout=10,
204
+ )
205
+ response.raise_for_status()
206
+
207
+ project_info = response.json()
208
+
209
+ if not project_info:
210
+ log.error(
211
+ "No project context found. Please ensure your API key is valid."
212
+ )
213
+
214
+ self.organization_id = project_info.get("organization_id")
215
+ self.workspace_id = project_info.get("workspace_id")
216
+ self.project_id = project_info.get("project_id")
217
+
218
+ if (
219
+ not self.organization_id
220
+ and not self.workspace_id
221
+ or not self.project_id
222
+ ):
223
+ log.error(
224
+ "Could not determine organization/workspace/project from API response."
225
+ )
226
+
227
+ except Exception as e:
228
+ log.error(f"Failed to fetch scope information: {e}")
229
+ return
230
+
231
+ if self.organization_id and self.workspace_id and self.project_id:
232
+ return (
233
+ self.organization_id,
234
+ self.workspace_id,
235
+ self.project_id,
236
+ )
237
+
238
+ return None
239
+
162
240
 
163
241
  class Config:
164
242
  def __init__(
agenta/sdk/assets.py CHANGED
@@ -1,3 +1,8 @@
1
+ from typing import Dict, Optional, Tuple
2
+
3
+ from litellm import cost_calculator
4
+
5
+
1
6
  supported_llm_models = {
2
7
  "anthropic": [
3
8
  "anthropic/claude-sonnet-4-5",
@@ -28,6 +33,7 @@ supported_llm_models = {
28
33
  ],
29
34
  "gemini": [
30
35
  "gemini/gemini-3-pro-preview",
36
+ "gemini/gemini-3-flash-preview",
31
37
  "gemini/gemini-2.5-pro",
32
38
  "gemini/gemini-2.5-pro-preview-05-06",
33
39
  "gemini/gemini-2.5-flash",
@@ -64,21 +70,26 @@ supported_llm_models = {
64
70
  "mistral/mistral-large-latest",
65
71
  ],
66
72
  "openai": [
67
- "gpt-5",
73
+ "gpt-5.2-pro",
74
+ "gpt-5.2-chat-latest",
75
+ "gpt-5.2",
76
+ "gpt-5.1-chat-latest",
68
77
  "gpt-5.1",
69
- "gpt-5-mini",
78
+ "gpt-5-pro",
70
79
  "gpt-5-nano",
80
+ "gpt-5-mini",
81
+ "gpt-5",
82
+ "o4-mini",
71
83
  "gpt-4.5-preview",
72
- "gpt-3.5-turbo-1106",
73
- "gpt-3.5-turbo",
74
- "gpt-4",
75
- "gpt-4o",
84
+ "gpt-4.1-nano",
85
+ "gpt-4.1-mini",
86
+ "gpt-4.1",
76
87
  "gpt-4o-mini",
88
+ "gpt-4o",
77
89
  "gpt-4-1106-preview",
78
- "gpt-4.1",
79
- "gpt-4.1-mini",
80
- "gpt-4.1-nano",
81
- "o4-mini",
90
+ "gpt-4",
91
+ "gpt-3.5-turbo-1106",
92
+ "gpt-3.5-turbo",
82
93
  ],
83
94
  "openrouter": [
84
95
  "openrouter/qwen/qwen3-235b-a22b",
@@ -200,6 +211,58 @@ supported_llm_models = {
200
211
 
201
212
  providers_list = list(supported_llm_models.keys())
202
213
 
214
+
215
+ def _get_model_costs(model: str) -> Optional[Tuple[float, float]]:
216
+ """
217
+ Get the input and output costs per 1M tokens for a model.
218
+
219
+ Uses litellm's cost_calculator (same as tracing/inline.py) for consistency.
220
+
221
+ Args:
222
+ model: The model name (e.g., "gpt-4o" or "anthropic/claude-3-opus-20240229")
223
+
224
+ Returns:
225
+ Tuple of (input_cost, output_cost) per 1M tokens, or None if not found.
226
+ """
227
+ try:
228
+ costs = cost_calculator.cost_per_token(
229
+ model=model,
230
+ prompt_tokens=1_000_000,
231
+ completion_tokens=1_000_000,
232
+ )
233
+ if costs:
234
+ input_cost, output_cost = costs
235
+ if input_cost > 0 or output_cost > 0:
236
+ return (input_cost, output_cost)
237
+ except Exception:
238
+ pass
239
+ return None
240
+
241
+
242
+ def _build_model_metadata() -> Dict[str, Dict[str, Dict[str, float]]]:
243
+ """
244
+ Build metadata dictionary with costs for all supported models.
245
+
246
+ Returns:
247
+ Nested dict: {provider: {model: {"input": cost, "output": cost}}}
248
+ """
249
+ metadata: Dict[str, Dict[str, Dict[str, float]]] = {}
250
+
251
+ for provider, models in supported_llm_models.items():
252
+ metadata[provider] = {}
253
+ for model in models:
254
+ costs = _get_model_costs(model)
255
+ if costs:
256
+ metadata[provider][model] = {
257
+ "input": costs[0],
258
+ "output": costs[1],
259
+ }
260
+
261
+ return metadata
262
+
263
+
264
+ model_metadata = _build_model_metadata()
265
+
203
266
  model_to_provider_mapping = {
204
267
  model: provider
205
268
  for provider, models in supported_llm_models.items()
@@ -1,53 +1,51 @@
1
- from typing import Type, Any, Callable, Dict, Optional, Tuple, List
1
+ from asyncio import sleep
2
+ from functools import wraps
2
3
  from inspect import (
4
+ Parameter,
5
+ Signature,
6
+ isasyncgen,
3
7
  iscoroutinefunction,
4
8
  isgenerator,
5
- isasyncgen,
6
9
  signature,
7
- Signature,
8
- Parameter,
9
10
  )
10
- from functools import wraps
11
+ from os import environ
11
12
  from traceback import format_exception
12
- from asyncio import sleep
13
+ from typing import Any, Callable, Dict, List, Optional, Tuple, Type
13
14
  from uuid import UUID
14
- from pydantic import BaseModel, HttpUrl, ValidationError
15
- from os import environ
16
-
17
- from starlette.responses import (
18
- Response as StarletteResponse,
19
- StreamingResponse,
20
- )
21
- from fastapi import Body, FastAPI, HTTPException, Request
22
-
23
- from agenta.sdk.middleware.mock import MockMiddleware
24
- from agenta.sdk.middleware.inline import InlineMiddleware
25
- from agenta.sdk.middleware.vault import VaultMiddleware
26
- from agenta.sdk.middleware.config import ConfigMiddleware
27
- from agenta.sdk.middleware.otel import OTelMiddleware
28
- from agenta.sdk.middleware.auth import AuthHTTPMiddleware
29
- from agenta.sdk.middleware.cors import CORSMiddleware
30
15
 
16
+ import agenta as ag
31
17
  from agenta.sdk.contexts.routing import (
32
- routing_context_manager,
33
18
  RoutingContext,
19
+ routing_context_manager,
34
20
  )
35
21
  from agenta.sdk.contexts.tracing import (
36
- tracing_context_manager,
37
22
  TracingContext,
23
+ tracing_context_manager,
38
24
  )
25
+ from agenta.sdk.middleware.auth import AuthHTTPMiddleware
26
+ from agenta.sdk.middleware.config import ConfigMiddleware
27
+ from agenta.sdk.middleware.cors import CORSMiddleware
28
+ from agenta.sdk.middleware.inline import InlineMiddleware
29
+ from agenta.sdk.middleware.mock import MockMiddleware
30
+ from agenta.sdk.middleware.otel import OTelMiddleware
31
+ from agenta.sdk.middleware.vault import VaultMiddleware
39
32
  from agenta.sdk.router import router
40
- from agenta.sdk.utils.exceptions import suppress, display_exception
41
- from agenta.sdk.utils.logging import get_module_logger
42
- from agenta.sdk.utils.helpers import get_current_version
43
33
  from agenta.sdk.types import (
44
- MultipleChoice,
45
34
  BaseResponse,
35
+ MultipleChoice,
46
36
  StreamResponse,
47
- MCField,
48
37
  )
49
-
50
- import agenta as ag
38
+ from agenta.sdk.utils.exceptions import display_exception, suppress
39
+ from agenta.sdk.utils.helpers import get_current_version
40
+ from agenta.sdk.utils.logging import get_module_logger
41
+ from fastapi import Body, FastAPI, HTTPException, Request
42
+ from pydantic import BaseModel, HttpUrl, ValidationError
43
+ from starlette.responses import (
44
+ Response as StarletteResponse,
45
+ )
46
+ from starlette.responses import (
47
+ StreamingResponse,
48
+ )
51
49
 
52
50
  log = get_module_logger(__name__)
53
51
 
@@ -1,36 +1,27 @@
1
1
  # /agenta/sdk/decorators/tracing.py
2
2
 
3
- from typing import Callable, Optional, Any, Dict, List, Union
4
-
5
- from opentelemetry import context as otel_context
6
- from opentelemetry.context import attach, detach
7
-
8
-
9
3
  from functools import wraps
10
- from itertools import chain
11
4
  from inspect import (
12
5
  getfullargspec,
6
+ isasyncgenfunction,
13
7
  iscoroutinefunction,
14
8
  isgeneratorfunction,
15
- isasyncgenfunction,
16
9
  )
10
+ from itertools import chain
11
+ from typing import Any, Callable, Dict, List, Optional, Union
17
12
 
18
- from pydantic import BaseModel
19
-
20
- from opentelemetry import baggage
21
- from opentelemetry.context import attach, detach, get_current
22
- from opentelemetry.baggage import set_baggage, get_all
23
-
24
- from agenta.sdk.utils.logging import get_module_logger
25
- from agenta.sdk.utils.exceptions import suppress
13
+ import agenta as ag
26
14
  from agenta.sdk.contexts.tracing import (
27
15
  TracingContext,
28
16
  tracing_context_manager,
29
17
  )
30
18
  from agenta.sdk.tracing.conventions import parse_span_kind
31
-
32
- import agenta as ag
33
-
19
+ from agenta.sdk.utils.exceptions import suppress
20
+ from agenta.sdk.utils.logging import get_module_logger
21
+ from opentelemetry import context as otel_context
22
+ from opentelemetry.baggage import get_all, set_baggage
23
+ from opentelemetry.context import attach, detach, get_current
24
+ from pydantic import BaseModel
34
25
 
35
26
  log = get_module_logger(__name__)
36
27
 
@@ -88,11 +79,12 @@ class instrument: # pylint: disable=invalid-name
88
79
  with tracing_context_manager(context=TracingContext.get()):
89
80
  # debug_otel_context("[BEFORE STREAM] [BEFORE SETUP]")
90
81
 
91
- captured_ctx = otel_context.get_current()
92
-
93
82
  self._parse_type_and_kind()
94
83
 
95
- self._attach_baggage()
84
+ baggage_token = self._attach_baggage()
85
+
86
+ # Capture AFTER baggage attach so we do not wipe it later.
87
+ captured_ctx = otel_context.get_current()
96
88
 
97
89
  ctx = self._get_traceparent()
98
90
 
@@ -141,6 +133,7 @@ class instrument: # pylint: disable=invalid-name
141
133
  otel_context.detach(otel_token)
142
134
 
143
135
  # debug_otel_context("[WITHIN STREAM] [AFTER DETACH]")
136
+ self._detach_baggage(baggage_token)
144
137
 
145
138
  return wrapped_generator()
146
139
 
@@ -311,15 +304,43 @@ class instrument: # pylint: disable=invalid-name
311
304
 
312
305
  def _attach_baggage(self):
313
306
  context = TracingContext.get()
307
+ otel_ctx = get_current()
308
+
309
+ # 1. Propagate any incoming `ag.*` baggage as-is (for example
310
+ # `ag.meta.session_id`) so all nested spans inherit it.
311
+ if context.baggage:
312
+ for k, v in context.baggage.items():
313
+ if not isinstance(k, str) or not k.startswith("ag."):
314
+ continue
315
+ if v is None:
316
+ continue
317
+ otel_ctx = set_baggage(name=k, value=str(v), context=otel_ctx)
318
+
319
+ # 2. Propagate Agenta references in baggage (used for linking traces to
320
+ # application/variant/environment).
321
+ if context.references:
322
+ for k, v in context.references.items():
323
+ if v is None:
324
+ continue
325
+ if isinstance(v, BaseModel):
326
+ try:
327
+ v = v.model_dump(mode="json", exclude_none=True)
328
+ except Exception: # pylint: disable=bare-except
329
+ pass
330
+ if isinstance(v, dict):
331
+ for field, value in v.items():
332
+ otel_ctx = set_baggage(
333
+ name=f"ag.refs.{k}.{field}",
334
+ value=str(value),
335
+ context=otel_ctx,
336
+ )
337
+ continue
338
+ otel_ctx = set_baggage(
339
+ name=f"ag.refs.{k}", value=str(v), context=otel_ctx
340
+ )
314
341
 
315
- references = context.references
316
-
317
- token = None
318
- if references:
319
- for k, v in references.items():
320
- token = attach(baggage.set_baggage(f"ag.refs.{k}", v))
321
-
322
- return token
342
+ # Attach once so we can reliably detach later.
343
+ return attach(otel_ctx)
323
344
 
324
345
  def _detach_baggage(
325
346
  self,
@@ -1,18 +1,17 @@
1
- from typing import Optional, Dict, List
2
1
  from threading import Lock
2
+ from typing import Dict, List, Optional
3
3
 
4
+ from agenta.sdk.models.tracing import BaseModel
5
+ from agenta.sdk.utils.logging import get_module_logger
4
6
  from opentelemetry.baggage import get_all as get_baggage
5
7
  from opentelemetry.context import Context
6
8
  from opentelemetry.sdk.trace import Span, SpanProcessor
7
9
  from opentelemetry.sdk.trace.export import (
8
- SpanExporter,
9
- ReadableSpan,
10
10
  BatchSpanProcessor,
11
+ ReadableSpan,
12
+ SpanExporter,
11
13
  )
12
14
 
13
- from agenta.sdk.utils.logging import get_module_logger
14
- from agenta.sdk.engines.tracing.conventions import Reference
15
-
16
15
  log = get_module_logger(__name__)
17
16
 
18
17
 
@@ -51,15 +50,27 @@ class TraceProcessor(SpanProcessor):
51
50
  parent_context: Optional[Context] = None,
52
51
  ) -> None:
53
52
  for key in self.references.keys():
54
- span.set_attribute(f"ag.refs.{key}", self.references[key])
53
+ ref = self.references[key]
54
+ if ref is None:
55
+ continue
56
+ if isinstance(ref, BaseModel):
57
+ try:
58
+ ref = ref.model_dump(mode="json", exclude_none=True)
59
+ except Exception: # pylint: disable=bare-except
60
+ pass
61
+ if isinstance(ref, dict):
62
+ for field, value in ref.items():
63
+ span.set_attribute(f"ag.refs.{key}.{field}", str(value))
64
+ else:
65
+ span.set_attribute(f"ag.refs.{key}", str(ref))
55
66
 
56
67
  baggage = get_baggage(parent_context)
57
68
 
58
- for key in baggage.keys():
59
- if key.startswith("ag.refs."):
60
- _key = key.replace("ag.refs.", "")
61
- if _key in [_.value for _ in Reference.__members__.values()]:
62
- span.set_attribute(key, baggage[key])
69
+ # Copy any `ag.*` baggage entries onto the span attributes so they can be
70
+ # used for filtering and grouping (for example `ag.meta.session_id`).
71
+ for key, value in baggage.items():
72
+ if key.startswith("ag."):
73
+ span.set_attribute(key, value)
63
74
 
64
75
  trace_id = span.context.trace_id
65
76
  span_id = span.context.span_id