witdem-analytics 0.2.2__tar.gz → 0.2.3__tar.gz

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.
Files changed (115) hide show
  1. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/PKG-INFO +1 -1
  2. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/pyproject.toml +1 -1
  3. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/operations.py +67 -24
  4. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/serving.py +9 -4
  5. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/.gitignore +0 -0
  6. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/LICENSE +0 -0
  7. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/README.md +0 -0
  8. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/__init__.py +0 -0
  9. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/adapters/__init__.py +0 -0
  10. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/adapters/base.py +0 -0
  11. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/adapters/haystack_adapter.py +0 -0
  12. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/adapters/providers.py +0 -0
  13. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/adapters/registry.py +0 -0
  14. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/__init__.py +0 -0
  15. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/contracts/__init__.py +0 -0
  16. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/contracts/read_models.py +0 -0
  17. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/core.py +0 -0
  18. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/cost.py +0 -0
  19. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/derived.py +0 -0
  20. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/identity.py +0 -0
  21. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/entities/models.sql +0 -0
  22. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/entities/provider_values.sql +0 -0
  23. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/entities/providers.sql +0 -0
  24. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/execution/business_outcome.sql +0 -0
  25. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/execution/evaluations_for_execution.sql +0 -0
  26. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/execution/events_for_execution.sql +0 -0
  27. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/execution/execution_detail.sql +0 -0
  28. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/execution/execution_population.sql +0 -0
  29. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/execution/execution_timeline.sql +0 -0
  30. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/execution/links_for_execution.sql +0 -0
  31. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/execution/outcomes_for_execution.sql +0 -0
  32. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/execution/product_goal.sql +0 -0
  33. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/execution/runtime_outcome.sql +0 -0
  34. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/failures/failure_patterns.sql +0 -0
  35. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/overview/cost_summary.sql +0 -0
  36. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/overview/execution_health.sql +0 -0
  37. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/overview/performance.sql +0 -0
  38. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/overview/product_goals.sql +0 -0
  39. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/overview/success_metrics.sql +0 -0
  40. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/paths/loops.sql +0 -0
  41. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/paths/path_frequency.sql +0 -0
  42. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/shared/capabilities.sql +0 -0
  43. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/shared/evaluations_count.sql +0 -0
  44. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/shared/events_capabilities.sql +0 -0
  45. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/shared/filter_completed.sql +0 -0
  46. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/shared/filter_end_date.sql +0 -0
  47. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/shared/filter_failed.sql +0 -0
  48. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/shared/filter_has_failure.sql +0 -0
  49. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/shared/filter_provider.sql +0 -0
  50. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/shared/filter_running.sql +0 -0
  51. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/shared/filter_start_date.sql +0 -0
  52. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/shared/metadata.sql +0 -0
  53. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/queries/shared/outcomes_count.sql +0 -0
  54. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/read_model.py +0 -0
  55. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/repository/__init__.py +0 -0
  56. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/repository/analytics_repository.py +0 -0
  57. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/repository/backend.py +0 -0
  58. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/repository/sql_loader.py +0 -0
  59. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/repository/state.py +0 -0
  60. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/runtime.py +0 -0
  61. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/schema/analytics_tables.sql +0 -0
  62. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/analytics/schema.py +0 -0
  63. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/api.py +0 -0
  64. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/auth.py +0 -0
  65. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/cli.py +0 -0
  66. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/config.py +0 -0
  67. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/dashboard/__init__.py +0 -0
  68. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/dashboard/app.py +0 -0
  69. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/dashboard/service.py +0 -0
  70. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/dashboard/static/assets/echarts-runtime-eFwAMB1Z.js +0 -0
  71. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/dashboard/static/assets/index-B2TO5dg7.css +0 -0
  72. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/dashboard/static/assets/index-BBNwEw42.js +0 -0
  73. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/dashboard/static/assets/witdem-mark-purple-B7xvtfh0.png +0 -0
  74. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/dashboard/static/index.html +0 -0
  75. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/elt/__init__.py +0 -0
  76. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/elt/adapter_stage.py +0 -0
  77. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/elt/publisher.py +0 -0
  78. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/elt/worker.py +0 -0
  79. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/elt/workspace/pipelines/normalize.pipeline.json +0 -0
  80. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/evaluation_campaigns.py +0 -0
  81. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/ingest/__init__.py +0 -0
  82. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/ingest/corpus.py +0 -0
  83. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/ingest/correlate.py +0 -0
  84. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/ingest/live_db.py +0 -0
  85. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/ingest/otlp_http.py +0 -0
  86. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/ingest/raw_store.py +0 -0
  87. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/ingest/sdk_ingest.py +0 -0
  88. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/ingest/sdk_store.py +0 -0
  89. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/integrations/__init__.py +0 -0
  90. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/integrations/adapters/__init__.py +0 -0
  91. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/integrations/adapters/claude.py +0 -0
  92. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/integrations/adapters/langchain.py +0 -0
  93. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/integrations/adapters/langgraph.py +0 -0
  94. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/integrations/adapters/openai_agents.py +0 -0
  95. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/integrations/adapters/otel.py +0 -0
  96. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/integrations/mapping.py +0 -0
  97. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/integrations/models/__init__.py +0 -0
  98. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/integrations/models/normalized_operation.py +0 -0
  99. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/integrations/models/normalized_span.py +0 -0
  100. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/integrations/normalizers/__init__.py +0 -0
  101. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/integrations/normalizers/genai.py +0 -0
  102. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/integrations/normalizers/openinference.py +0 -0
  103. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/integrations/normalizers/otel.py +0 -0
  104. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/lifecycle.py +0 -0
  105. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/pricing/__init__.py +0 -0
  106. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/pricing/catalog.yaml +0 -0
  107. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/pricing/sources.yaml +0 -0
  108. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/pricing/update.py +0 -0
  109. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/protocol.py +0 -0
  110. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/py.typed +0 -0
  111. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/retention.py +0 -0
  112. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/telemetry/__init__.py +0 -0
  113. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/telemetry/otel.py +0 -0
  114. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/update.py +0 -0
  115. {witdem_analytics-0.2.2 → witdem_analytics-0.2.3}/src/witdem/workflows.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: witdem-analytics
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Runtime analytics for agent applications using OpenTelemetry, with optional business semantics through the Witdem SDK.
5
5
  License-File: LICENSE
6
6
  Classifier: Programming Language :: Python :: 3
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "witdem-analytics"
7
- version = "0.2.2"
7
+ version = "0.2.3"
8
8
  description = "Runtime analytics for agent applications using OpenTelemetry, with optional business semantics through the Witdem SDK."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10,<3.14"
@@ -63,6 +63,9 @@ OPERATION_FAMILIES: dict[str, OperationFamily] = {
63
63
  "mcp_resource_read": "mcp",
64
64
  "mcp_prompt_retrieval": "mcp",
65
65
  "mcp_capability_discovery": "mcp",
66
+ "capability_discovery": "mcp",
67
+ "resource_read": "knowledge",
68
+ "prompt_retrieval": "knowledge",
66
69
  "planning": "agent_control",
67
70
  "delegation": "agent_control",
68
71
  "handoff": "agent_control",
@@ -148,6 +151,14 @@ OTEL_OPERATION_TYPES = {
148
151
  "invoke_workflow": "workflow",
149
152
  }
150
153
 
154
+ MCP_OPERATION_TYPES = {
155
+ "initialize": "mcp_connection",
156
+ "tools/list": "capability_discovery",
157
+ "resources/read": "resource_read",
158
+ "prompts/get": "prompt_retrieval",
159
+ "tools/call": "tool",
160
+ }
161
+
151
162
  OPENINFERENCE_OPERATION_TYPES = {
152
163
  "LLM": "text_generation",
153
164
  "EMBEDDING": "embedding",
@@ -203,15 +214,37 @@ _BOUNDED_NAME_MARKERS = (
203
214
 
204
215
  VALID_FAMILIES = frozenset(
205
216
  {
206
- "orchestration", "inference", "knowledge", "tools", "mcp", "agent_control",
207
- "media", "quality", "memory", "human_work", "external_action", "data_movement",
208
- "action", "custom",
217
+ "orchestration",
218
+ "inference",
219
+ "knowledge",
220
+ "tools",
221
+ "mcp",
222
+ "agent_control",
223
+ "media",
224
+ "quality",
225
+ "memory",
226
+ "human_work",
227
+ "external_action",
228
+ "data_movement",
229
+ "action",
230
+ "custom",
209
231
  }
210
232
  )
211
233
  VALID_INTERFACES = frozenset(
212
234
  {
213
- "model_api", "tool", "framework", "datastore", "vector_database", "search_service",
214
- "mcp", "library", "local", "external_api", "browser", "human", "unknown",
235
+ "model_api",
236
+ "tool",
237
+ "framework",
238
+ "datastore",
239
+ "vector_database",
240
+ "search_service",
241
+ "mcp",
242
+ "library",
243
+ "local",
244
+ "external_api",
245
+ "browser",
246
+ "human",
247
+ "unknown",
215
248
  }
216
249
  )
217
250
  VALID_ROLES = frozenset(
@@ -222,7 +255,7 @@ VALID_ENTITY_KINDS = frozenset({"execution", "operation", "business_event"})
222
255
  VALID_PLANES = frozenset({"control", "work", "business"})
223
256
 
224
257
  _CONTROL_FAMILIES = frozenset({"orchestration", "agent_control"})
225
- _CONTROL_MCP_TYPES = frozenset({"mcp_connection", "mcp_server", "mcp_capability_discovery"})
258
+ _CONTROL_MCP_TYPES = frozenset({"mcp_connection", "mcp_server", "mcp_capability_discovery", "capability_discovery"})
226
259
  _MODEL_APPLICABLE_FAMILIES = frozenset({"inference", "media"})
227
260
 
228
261
 
@@ -498,6 +531,7 @@ def operation_identity(operation: Operation) -> dict[str, Any]:
498
531
  attributes = operation.attributes
499
532
  explicit_type = str(attributes.get("witdem.operation.type") or "").strip().casefold()
500
533
  otel_name = str(attributes.get("gen_ai.operation.name") or "").strip().casefold()
534
+ mcp_method = str(attributes.get("mcp.method.name") or "").strip().casefold()
501
535
  oi_kind = str(attributes.get("openinference.span.kind") or attributes.get("openinference.kind") or "").upper()
502
536
  adapter_type = next(
503
537
  (
@@ -521,16 +555,21 @@ def operation_identity(operation: Operation) -> dict[str, Any]:
521
555
  operation_type = (
522
556
  explicit_type
523
557
  or OTEL_OPERATION_TYPES.get(otel_name)
558
+ or MCP_OPERATION_TYPES.get(mcp_method)
524
559
  or OPENINFERENCE_OPERATION_TYPES.get(oi_kind)
525
560
  or adapter_type
526
561
  or _bounded_metadata_type(operation)
527
562
  )
528
563
  if not operation_type:
529
- operation_type = ({
530
- "workflow": "workflow",
531
- "pipeline": "workflow",
532
- "agent": "agent",
533
- }.get(runtime_kind) if entity_kind == "execution" else None) or {
564
+ operation_type = (
565
+ {
566
+ "workflow": "workflow",
567
+ "pipeline": "workflow",
568
+ "agent": "agent",
569
+ }.get(runtime_kind)
570
+ if entity_kind == "execution"
571
+ else None
572
+ ) or {
534
573
  "workflow": "workflow",
535
574
  "pipeline": "workflow",
536
575
  "agent": "agent",
@@ -544,7 +583,9 @@ def operation_identity(operation: Operation) -> dict[str, Any]:
544
583
  interface = str(attributes.get("witdem.operation.interface") or "").strip().casefold()
545
584
  if interface not in VALID_INTERFACES:
546
585
  interface = (
547
- "tool"
586
+ "mcp"
587
+ if mcp_method
588
+ else "tool"
548
589
  if operation.kind == "tool"
549
590
  else "model_api"
550
591
  if family in {"inference", "media"}
@@ -562,26 +603,28 @@ def operation_identity(operation: Operation) -> dict[str, Any]:
562
603
  if family in _CONTROL_FAMILIES or operation_type in _CONTROL_MCP_TYPES
563
604
  else "work"
564
605
  )
565
- role = str(
566
- attributes.get("witdem.operation.role")
567
- or ("control" if plane == "control" else "application")
568
- ).strip().casefold()
606
+ role = (
607
+ str(
608
+ attributes.get("witdem.operation.role")
609
+ or ("tool" if mcp_method == "tools/call" else None)
610
+ or ("control" if plane == "control" else "application")
611
+ )
612
+ .strip()
613
+ .casefold()
614
+ )
569
615
  if role not in VALID_ROLES:
570
616
  role = "application"
571
- model_reported = any(
572
- attributes.get(key)
573
- for key in ("gen_ai.response.model", "gen_ai.request.model", "model")
574
- )
575
- model_applicability = (
576
- "applicable" if model_reported or family in _MODEL_APPLICABLE_FAMILIES else "not_applicable"
577
- )
617
+ model_reported = any(attributes.get(key) for key in ("gen_ai.response.model", "gen_ai.request.model", "model"))
618
+ model_applicability = "applicable" if model_reported or family in _MODEL_APPLICABLE_FAMILIES else "not_applicable"
578
619
  return {
579
620
  "taxonomy_version": OPERATION_TAXONOMY_VERSION,
580
621
  "entity_kind": entity_kind,
581
622
  "plane": plane,
582
623
  "family": family,
583
624
  "type": operation_type,
584
- "subtype": str(attributes.get("witdem.operation.subtype") or otel_name or oi_kind or operation.name),
625
+ "subtype": str(
626
+ attributes.get("witdem.operation.subtype") or otel_name or mcp_method or oi_kind or operation.name
627
+ ),
585
628
  "interface": interface,
586
629
  "role": role,
587
630
  "model_applicability": model_applicability,
@@ -236,13 +236,18 @@ def build_serving_rows(
236
236
  operation
237
237
  for operation in operations
238
238
  if operation.kind == "model"
239
+ or (model_value(operation) is not None and operation_identity(operation)["family"] in {"inference", "media"})
240
+ ]
241
+ model_identity_operations = [operation for operation in operations if model_value(operation) is not None]
242
+ tool_operations = [
243
+ operation
244
+ for operation in operations
245
+ if operation.kind == "tool"
239
246
  or (
240
- model_value(operation) is not None
241
- and operation_identity(operation)["family"] in {"inference", "media"}
247
+ operation_identity(operation)["entity_kind"] == "operation"
248
+ and operation_identity(operation)["type"] in {"tool", "tool_execution"}
242
249
  )
243
250
  ]
244
- model_identity_operations = [operation for operation in operations if model_value(operation) is not None]
245
- tool_operations = [operation for operation in operations if operation.kind == "tool"]
246
251
  failures = [operation for operation in operations if operation.status == "error"]
247
252
  goal: dict[str, Any] = {}
248
253
  application_outcome: str | None = None