diff --git a/api/oss/src/apis/fastapi/tracing/router.py b/api/oss/src/apis/fastapi/tracing/router.py index 91f2de01fb..7774a6f9c4 100644 --- a/api/oss/src/apis/fastapi/tracing/router.py +++ b/api/oss/src/apis/fastapi/tracing/router.py @@ -301,7 +301,7 @@ async def ingest_spans( # MUTATION ) link_response = OTelLinksResponse( - count=len(links) + len(dropped), + count=len(links), links=links, dropped=dropped or None, ) diff --git a/api/oss/src/core/queries/dtos.py b/api/oss/src/core/queries/dtos.py index c467f488bc..d8c35b6300 100644 --- a/api/oss/src/core/queries/dtos.py +++ b/api/oss/src/core/queries/dtos.py @@ -1,7 +1,7 @@ from typing import List, Optional from uuid import UUID -from pydantic import BaseModel, Field +from pydantic import BaseModel, ConfigDict, Field from oss.src.core.tracing.dtos import Filtering, Formatting @@ -119,6 +119,8 @@ class QueryVariantQuery(VariantQuery): class QueryRevisionData(BaseModel): + model_config = ConfigDict(extra="forbid") + formatting: Optional[Formatting] = None filtering: Optional[Filtering] = None windowing: Optional[Windowing] = None diff --git a/api/oss/src/core/shared/exceptions.py b/api/oss/src/core/shared/exceptions.py index fc903492b4..e5647914cb 100644 --- a/api/oss/src/core/shared/exceptions.py +++ b/api/oss/src/core/shared/exceptions.py @@ -18,7 +18,8 @@ def __init__( def __str__(self): _message = self.message - for key, value in self.conflict.items(): - _message += f" {key}={value}" + if self.conflict: + for key, value in self.conflict.items(): + _message += f" {key}={value}" return _message diff --git a/api/oss/src/core/testsets/dtos.py b/api/oss/src/core/testsets/dtos.py index a8697d70a2..c81ec5921b 100644 --- a/api/oss/src/core/testsets/dtos.py +++ b/api/oss/src/core/testsets/dtos.py @@ -1,7 +1,7 @@ from typing import Optional, List, Tuple from uuid import UUID -from pydantic import BaseModel, Field +from pydantic import BaseModel, ConfigDict, Field from oss.src.core.shared.dtos import ( sync_alias, @@ -134,6 +134,8 @@ class TestsetVariantQuery(VariantQuery): class TestsetRevisionData(BaseModel): + model_config = ConfigDict(extra="forbid") + testcase_ids: Optional[List[UUID]] = None testcases: Optional[List[Testcase]] = None diff --git a/docs/docs/reference/api-guide/10-tracing.mdx b/docs/docs/reference/api-guide/10-tracing.mdx index 24d87d92ee..53b10a8400 100644 --- a/docs/docs/reference/api-guide/10-tracing.mdx +++ b/docs/docs/reference/api-guide/10-tracing.mdx @@ -56,7 +56,7 @@ Each span also declares its role through `ag.type.span`: | `chat`, `completion` | Chat-completion or completion calls. | | `embedding`, `query`, `rerank` | Index and retrieval calls. | -## References +## References {#references-and-entity-linking} A reference links a trace (or a span) back to the Agenta entity that produced or triggered it. References live under `ag.references.` and each value names an entity revision: @@ -125,7 +125,7 @@ The Agenta-native ingest endpoints `POST /tracing/spans/ingest` and `POST /trace ::: -### How ingest works +### How ingest works {#async-write-contract-202} Every ingest endpoint returns `202 Accepted` *before* the spans are persisted. The router parses the payload, hands the spans off to an async worker, and responds immediately. This keeps the ingest buffer fast, so instrumented apps do not block on telemetry. diff --git a/sdks/python/agenta/sdk/engines/running/templates.py b/sdks/python/agenta/sdk/engines/running/templates.py index 4472b76c94..813b50910a 100644 --- a/sdks/python/agenta/sdk/engines/running/templates.py +++ b/sdks/python/agenta/sdk/engines/running/templates.py @@ -66,13 +66,11 @@ {user_code} // Execute and capture result -let result = evaluate(app_params, inputs, output, correct_answer); +let result: number | null = evaluate(app_params, inputs, output, correct_answer); // Ensure result is a number -result = Number(result); -if (!Number.isFinite(result)) {{ - result = null; -}} +const resultNum = Number(result); +result = Number.isFinite(resultNum) ? resultNum : null; // Print result for capture console.log(JSON.stringify({{ result: result }})); @@ -137,13 +135,11 @@ {user_code} // Execute and capture result -let result = evaluate(inputs, outputs, trace); +let result: number | null = evaluate(inputs, outputs, trace); // Ensure result is a number -result = Number(result); -if (!Number.isFinite(result)) {{ - result = null; -}} +const resultNum = Number(result); +result = Number.isFinite(resultNum) ? resultNum : null; // Print result for capture console.log(JSON.stringify({{ result: result }})); diff --git a/sdks/python/agenta/sdk/models/workflows.py b/sdks/python/agenta/sdk/models/workflows.py index 67dfc3ac21..086c4ece93 100644 --- a/sdks/python/agenta/sdk/models/workflows.py +++ b/sdks/python/agenta/sdk/models/workflows.py @@ -119,6 +119,8 @@ class WorkflowQueryFlags(BaseModel): class WorkflowRevisionData(BaseModel): + model_config = ConfigDict(extra="forbid") + uri: Optional[str] = None url: Optional[str] = None