Skip to content

Conversation

@DavidJJ
Copy link

@DavidJJ DavidJJ commented Dec 17, 2025

This change is primarily to fix an issue where if you try to create a trace span using a List instead of a dictionary or BaseModel it errored out even though the upper function signature specified that List[Any] is allowed.

To be able to verify this with built in tests I had to update the requirements * .lock files and then the uv.lock file also got updated.

This all resulted in no longer needing or being required to limit the nox session to pydantic 1.x and it was failing because the code wants pydantic 2 so i removed the pydantic 1.x requirement from the nox file.

This change is primarily to fix an issue where if you try to create a trace span using a List instead of a dictionary or BaseModel it errored out even though the upper function signature specified that List[Any] is allowed.

To be able to verify this with built in tests I had to update the requirements * .lock files and then the uv.lock file also got updated.

This all resulted in no longer needing or being required to limit the nox session to pydantic 1.x and it was failing because the code wants pydantic 2 so i removed the pydantic 1.x requirement from the nox file.
@socket-security
Copy link

socket-security bot commented Dec 17, 2025

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedagentex-sdk@​0.6.7 ⏵ 0.7.3100 +14100100100100

View full report

@danielmillerp danielmillerp self-requested a review December 17, 2025 19:12
input: dict[str, Any] | list[dict[str, Any]] | BaseModel | None = None,
data: dict[str, Any] | list[dict[str, Any]] | BaseModel | None = None,
input: dict[str, Any] | list[Any] | BaseModel | None = None,
data: dict[str, Any] | list[Any] | BaseModel | None = None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this will work because the Span object has this restriction too.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change makes the trace input signature match the Span input signature.

I found this because I was trying to do span( input=['a string here']) which is valid for the span signature. but failed when it got down to the trace.

I followed the code down into the dump object function to verify that it could handle a list of Any and then decided to make trace match span instead of span match trace.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the context. I traced through the code more carefully and I think there might be some confusion about what the Span signature actually accepts.

Looking at types/span.py, the Span model has:
input: Union[Dict[str, object], List[Dict[str, object]], None] = None

But ['a string here'] is a List[str], not a List[Dict[str, object]], so it technically doesn't match the Span signature either.

More importantly, I tested this and even if the local code accepts it, the SGP API backend rejects it with:
Error code: 422 - {'detail': [{'type': 'dict_type', 'loc': ['body', 'items', 0, 'input'], 'msg': 'Input should be a valid
dictionary', 'input': [...]}]}

This happens in sgp_tracing_processor.py when it calls spans.upsert_batch().

Can you confirm you were able to successfully create a span with input=['a string here'] end-to-end? Or did it fail at the API level?

name=name,
parent_id=parent_id,
start_time=start_time,
input=serialized_input,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the type here is : data: Union[Dict[str, object], List[Dict[str, object]], None] = None
"""Any additional metadata or context for the span"""

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the source code for tracing.py:

`@asynccontextmanager
async def span(
self,
trace_id: str,
name: str,
input: list[Any] | dict[str, Any] | BaseModel | None = None,
data: list[Any] | dict[str, Any] | BaseModel | None = None,
parent_id: str | None = None,
start_to_close_timeout: timedelta = timedelta(seconds=5),
heartbeat_timeout: timedelta = timedelta(seconds=5),
retry_policy: RetryPolicy = DEFAULT_RETRY_POLICY,
) -> AsyncGenerator[Span | None, None]:
"""
Async context manager for creating and automatically closing a span.
Yields the started span object. The span is automatically ended when the context exits.

    If trace_id is falsy, acts as a no-op context manager.

    Args:
        trace_id (str): The trace ID for the span.
        name (str): The name of the span.
        input (Union[List, Dict, BaseModel]): The input for the span.
        parent_id (Optional[str]): The parent span ID for the span.
        data (Optional[Union[List, Dict, BaseModel]]): The data for the span.
        start_to_close_timeout (timedelta): The start to close timeout for the span.
        heartbeat_timeout (timedelta): The heartbeat timeout for the span.
        retry_policy (RetryPolicy): The retry policy for the span.

    Returns:
        AsyncGenerator[Optional[Span], None]: An async generator that yields the started span object.
    """`

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see - you're pointing to TracingModule.span() in adk/_modules/tracing.py, which does accept list[Any]. So the mismatch you found is:

TracingModule.span() → list[Any] ✅ (adk/_modules/tracing.py)

AsyncTrace.span() → list[dict[str, Any]] ❌ (core/tracing/trace.py - your fix)

Span model → List[Dict[str, object]] (types/span.py)

SGP API → Dict only

Your fix aligns trace.py with the upper TracingModule layer - that part makes sense.

The issue is the chain continues downward. Even with your fix, passing ['a string'] will still hit restrictions at:

  1. The Span model (List[Dict[str, object]], not List[Any])
  2. The SGP API (rejects non-dict values for input)

Did you test this end-to-end with input=['a string']? I'm getting a 422 from the API when the span is sent to the backend via sgp_tracing_processor.

If the goal is to support list[Any] fully, we'd need the API team to update the backend as well.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with ether way, just need the documentation, and signatures of actually used code to match.

I have not been able to get my local adk package to integrate with the agentex platform as signatures don't match what is expected. So i have not been able to do end-to-end testing. I would appreciate guidance on that if possible so I can better test changes in the future.

@danielmillerp
Copy link
Contributor

This change is primarily to fix an issue where if you try to create a trace span using a List instead of a dictionary or BaseModel it errored out even though the upper function signature specified that List[Any] is allowed.

To be able to verify this with built in tests I had to update the requirements * .lock files and then the uv.lock file also got updated.

This all resulted in no longer needing or being required to limit the nox session to pydantic 1.x and it was failing because the code wants pydantic 2 so i removed the pydantic 1.x requirement from the nox file.

potentially a better solution would be to change the top level tracing so it is an honest type check

…not allowing List[Any]

This flips the fix on it's head and instead of allowing List[Any] goes the other way and requires that a list be a List[Dict[str, Any]] which
is what the deeper SPAN object actually wants.

I noticed that the `data` parameter suffers the same lack of type consistency that the `input` parameter had where the SPAN object actually specifies only dicts and lists of dicts are accepted, but upper level functions allow list[Any] so I normalized those as well.
@DavidJJ
Copy link
Author

DavidJJ commented Dec 18, 2025

I reversed the fix so that it goes the other way: requires List[Dict[str, Any]] all the way up the chain.

Also noticed that the same inconsistency exists for the data parameter so I also normalized the types on that as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants