Skip to content
This repository was archived by the owner on Oct 1, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions gradient_adk/cli/agent/traces_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,24 @@ async def open_traces_console(
deployment = deployment_output.agent_workspace_deployment
logging_config = deployment.logging_config

# AAPP-1104: a deployment created during a Galileo outage may carry
# logging_config = None (or partially-populated fields). The Traces
# console URL needs both project_id and log_stream_id to be present,
# so surface a clean message to the operator instead of crashing on
# attribute access.
if (
logging_config is None
or not logging_config.galileo_project_id
or not logging_config.log_stream_id
):
raise ValueError(
f"Tracing is not provisioned for agent deployment "
f"'{agent_deployment_name}' in workspace '{agent_workspace_name}'. "
"This usually means the deployment was created while the tracing "
"service was unavailable. Retry once Galileo is healthy, or "
"redeploy the agent."
)

# Get tracing token using workspace UUID
tracing_token: TracingServiceJWTOutput = await self.client.get_tracing_token(
agent_workspace_uuid=workspace_uuid,
Expand Down
22 changes: 18 additions & 4 deletions gradient_adk/digital_ocean_api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,14 +256,28 @@ class AgentDeploymentRelease(BaseModel):
class AgentLoggingConfig(BaseModel):
"""
Represents Agent Logging Config Details.

AAPP-1104: every Galileo-derived field is now Optional. The backend may
return an AgentLoggingConfig with these fields unset when an agent or
deployment was created during a Galileo outage and provisioning was
deferred. Callers must handle the None case explicitly (see TracesService
for the canonical pattern) and not assume the fields are populated.
"""

model_config = ConfigDict(populate_by_name=True, extra="allow")

galileo_project_id: str = Field(..., description="Galileo project identifier")
galileo_project_name: str = Field(..., description="Name of the Galileo project")
log_stream_id: str = Field(..., description="Identifier for the log stream")
log_stream_name: str = Field(..., description="Name of the log stream")
galileo_project_id: Optional[str] = Field(
None, description="Galileo project identifier"
)
galileo_project_name: Optional[str] = Field(
None, description="Name of the Galileo project"
)
log_stream_id: Optional[str] = Field(
None, description="Identifier for the log stream"
)
log_stream_name: Optional[str] = Field(
None, description="Name of the log stream"
)
insights_enabled_at: Optional[datetime] = Field(
None, description="Timestamp when insights were enabled (RFC3339 timestamp)"
)
Expand Down
Loading