agent_os_kernel 3.1.0__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.
Files changed (337) hide show
  1. agent_control_plane/__init__.py +662 -0
  2. agent_control_plane/a2a_adapter.py +543 -0
  3. agent_control_plane/adapter.py +417 -0
  4. agent_control_plane/agent_hibernation.py +394 -0
  5. agent_control_plane/agent_kernel.py +470 -0
  6. agent_control_plane/compliance.py +720 -0
  7. agent_control_plane/constraint_graphs.py +478 -0
  8. agent_control_plane/control_plane.py +854 -0
  9. agent_control_plane/example_executors.py +195 -0
  10. agent_control_plane/execution_engine.py +231 -0
  11. agent_control_plane/flight_recorder.py +846 -0
  12. agent_control_plane/governance_layer.py +435 -0
  13. agent_control_plane/hf_utils.py +563 -0
  14. agent_control_plane/interfaces/__init__.py +55 -0
  15. agent_control_plane/interfaces/kernel_interface.py +361 -0
  16. agent_control_plane/interfaces/plugin_interface.py +497 -0
  17. agent_control_plane/interfaces/protocol_interfaces.py +387 -0
  18. agent_control_plane/kernel_space.py +1009 -0
  19. agent_control_plane/langchain_adapter.py +424 -0
  20. agent_control_plane/lifecycle.py +3113 -0
  21. agent_control_plane/mcp_adapter.py +653 -0
  22. agent_control_plane/ml_safety.py +563 -0
  23. agent_control_plane/multimodal.py +727 -0
  24. agent_control_plane/mute_agent.py +422 -0
  25. agent_control_plane/observability.py +787 -0
  26. agent_control_plane/orchestrator.py +482 -0
  27. agent_control_plane/plugin_registry.py +750 -0
  28. agent_control_plane/policy_engine.py +954 -0
  29. agent_control_plane/process_isolation.py +777 -0
  30. agent_control_plane/shadow_mode.py +310 -0
  31. agent_control_plane/signals.py +493 -0
  32. agent_control_plane/supervisor_agents.py +430 -0
  33. agent_control_plane/time_travel_debugger.py +557 -0
  34. agent_control_plane/tool_registry.py +452 -0
  35. agent_control_plane/vfs.py +697 -0
  36. agent_kernel/__init__.py +69 -0
  37. agent_kernel/analyzer.py +435 -0
  38. agent_kernel/auditor.py +36 -0
  39. agent_kernel/completeness_auditor.py +237 -0
  40. agent_kernel/detector.py +203 -0
  41. agent_kernel/kernel.py +744 -0
  42. agent_kernel/memory_manager.py +85 -0
  43. agent_kernel/models.py +374 -0
  44. agent_kernel/nudge_mechanism.py +263 -0
  45. agent_kernel/outcome_analyzer.py +338 -0
  46. agent_kernel/patcher.py +582 -0
  47. agent_kernel/semantic_analyzer.py +316 -0
  48. agent_kernel/semantic_purge.py +349 -0
  49. agent_kernel/simulator.py +449 -0
  50. agent_kernel/teacher.py +85 -0
  51. agent_kernel/triage.py +152 -0
  52. agent_os/__init__.py +409 -0
  53. agent_os/_adversarial_impl.py +200 -0
  54. agent_os/_circuit_breaker_impl.py +232 -0
  55. agent_os/_mcp_metrics.py +193 -0
  56. agent_os/adversarial.py +20 -0
  57. agent_os/agents_compat.py +490 -0
  58. agent_os/audit_logger.py +135 -0
  59. agent_os/base_agent.py +651 -0
  60. agent_os/circuit_breaker.py +34 -0
  61. agent_os/cli/__init__.py +659 -0
  62. agent_os/cli/cmd_audit.py +128 -0
  63. agent_os/cli/cmd_init.py +152 -0
  64. agent_os/cli/cmd_policy.py +41 -0
  65. agent_os/cli/cmd_policy_gen.py +180 -0
  66. agent_os/cli/cmd_validate.py +258 -0
  67. agent_os/cli/mcp_scan.py +265 -0
  68. agent_os/cli/output.py +192 -0
  69. agent_os/cli/policy_checker.py +330 -0
  70. agent_os/compat.py +74 -0
  71. agent_os/constraint_graph.py +234 -0
  72. agent_os/content_governance.py +140 -0
  73. agent_os/context_budget.py +305 -0
  74. agent_os/credential_redactor.py +224 -0
  75. agent_os/diff_policy.py +89 -0
  76. agent_os/egress_policy.py +159 -0
  77. agent_os/escalation.py +276 -0
  78. agent_os/event_bus.py +124 -0
  79. agent_os/exceptions.py +180 -0
  80. agent_os/execution_context_policy.py +141 -0
  81. agent_os/github_enterprise.py +96 -0
  82. agent_os/health.py +20 -0
  83. agent_os/integrations/__init__.py +279 -0
  84. agent_os/integrations/a2a_adapter.py +279 -0
  85. agent_os/integrations/agent_lightning/__init__.py +30 -0
  86. agent_os/integrations/anthropic_adapter.py +420 -0
  87. agent_os/integrations/autogen_adapter.py +620 -0
  88. agent_os/integrations/base.py +1137 -0
  89. agent_os/integrations/compat.py +229 -0
  90. agent_os/integrations/config.py +98 -0
  91. agent_os/integrations/conversation_guardian.py +957 -0
  92. agent_os/integrations/crewai_adapter.py +467 -0
  93. agent_os/integrations/drift_detector.py +425 -0
  94. agent_os/integrations/dry_run.py +124 -0
  95. agent_os/integrations/escalation.py +582 -0
  96. agent_os/integrations/gemini_adapter.py +364 -0
  97. agent_os/integrations/google_adk_adapter.py +633 -0
  98. agent_os/integrations/guardrails_adapter.py +394 -0
  99. agent_os/integrations/health.py +197 -0
  100. agent_os/integrations/langchain_adapter.py +654 -0
  101. agent_os/integrations/llamafirewall.py +343 -0
  102. agent_os/integrations/llamaindex_adapter.py +188 -0
  103. agent_os/integrations/logging.py +191 -0
  104. agent_os/integrations/maf_adapter.py +631 -0
  105. agent_os/integrations/mistral_adapter.py +365 -0
  106. agent_os/integrations/openai_adapter.py +816 -0
  107. agent_os/integrations/openai_agents_sdk.py +406 -0
  108. agent_os/integrations/policy_compose.py +171 -0
  109. agent_os/integrations/profiling.py +144 -0
  110. agent_os/integrations/pydantic_ai_adapter.py +420 -0
  111. agent_os/integrations/rate_limiter.py +130 -0
  112. agent_os/integrations/rbac.py +143 -0
  113. agent_os/integrations/registry.py +113 -0
  114. agent_os/integrations/scope_guard.py +303 -0
  115. agent_os/integrations/semantic_kernel_adapter.py +769 -0
  116. agent_os/integrations/smolagents_adapter.py +629 -0
  117. agent_os/integrations/templates.py +178 -0
  118. agent_os/integrations/token_budget.py +134 -0
  119. agent_os/integrations/tool_aliases.py +190 -0
  120. agent_os/integrations/webhooks.py +177 -0
  121. agent_os/lite.py +208 -0
  122. agent_os/mcp_gateway.py +385 -0
  123. agent_os/mcp_message_signer.py +273 -0
  124. agent_os/mcp_protocols.py +161 -0
  125. agent_os/mcp_response_scanner.py +232 -0
  126. agent_os/mcp_security.py +924 -0
  127. agent_os/mcp_session_auth.py +231 -0
  128. agent_os/mcp_sliding_rate_limiter.py +184 -0
  129. agent_os/memory_guard.py +409 -0
  130. agent_os/metrics.py +134 -0
  131. agent_os/mute.py +428 -0
  132. agent_os/mute_agent.py +209 -0
  133. agent_os/policies/__init__.py +77 -0
  134. agent_os/policies/async_evaluator.py +275 -0
  135. agent_os/policies/backends.py +670 -0
  136. agent_os/policies/bridge.py +169 -0
  137. agent_os/policies/budget.py +85 -0
  138. agent_os/policies/cli.py +294 -0
  139. agent_os/policies/conflict_resolution.py +270 -0
  140. agent_os/policies/data_classification.py +252 -0
  141. agent_os/policies/evaluator.py +239 -0
  142. agent_os/policies/policy_schema.json +228 -0
  143. agent_os/policies/rate_limiting.py +145 -0
  144. agent_os/policies/schema.py +115 -0
  145. agent_os/policies/shared.py +331 -0
  146. agent_os/prompt_injection.py +694 -0
  147. agent_os/providers.py +182 -0
  148. agent_os/py.typed +0 -0
  149. agent_os/retry.py +81 -0
  150. agent_os/reversibility.py +251 -0
  151. agent_os/sandbox.py +432 -0
  152. agent_os/sandbox_provider.py +140 -0
  153. agent_os/secure_codegen.py +525 -0
  154. agent_os/security_skills.py +538 -0
  155. agent_os/semantic_policy.py +422 -0
  156. agent_os/server/__init__.py +15 -0
  157. agent_os/server/__main__.py +25 -0
  158. agent_os/server/app.py +277 -0
  159. agent_os/server/models.py +104 -0
  160. agent_os/shift_left_metrics.py +130 -0
  161. agent_os/stateless.py +742 -0
  162. agent_os/supervisor.py +148 -0
  163. agent_os/task_outcome.py +148 -0
  164. agent_os/transparency.py +181 -0
  165. agent_os/trust_root.py +128 -0
  166. agent_os_kernel-3.1.0.dist-info/METADATA +1269 -0
  167. agent_os_kernel-3.1.0.dist-info/RECORD +337 -0
  168. agent_os_kernel-3.1.0.dist-info/WHEEL +4 -0
  169. agent_os_kernel-3.1.0.dist-info/entry_points.txt +2 -0
  170. agent_os_kernel-3.1.0.dist-info/licenses/LICENSE +21 -0
  171. agent_os_observability/__init__.py +27 -0
  172. agent_os_observability/dashboards.py +898 -0
  173. agent_os_observability/metrics.py +398 -0
  174. agent_os_observability/server.py +223 -0
  175. agent_os_observability/tracer.py +232 -0
  176. agent_primitives/__init__.py +24 -0
  177. agent_primitives/failures.py +84 -0
  178. agent_primitives/py.typed +0 -0
  179. amb_core/__init__.py +177 -0
  180. amb_core/adapters/__init__.py +57 -0
  181. amb_core/adapters/aws_sqs_broker.py +376 -0
  182. amb_core/adapters/azure_servicebus_broker.py +340 -0
  183. amb_core/adapters/kafka_broker.py +260 -0
  184. amb_core/adapters/nats_broker.py +285 -0
  185. amb_core/adapters/rabbitmq_broker.py +235 -0
  186. amb_core/adapters/redis_broker.py +262 -0
  187. amb_core/broker.py +145 -0
  188. amb_core/bus.py +481 -0
  189. amb_core/cloudevents.py +509 -0
  190. amb_core/dlq.py +345 -0
  191. amb_core/hf_utils.py +536 -0
  192. amb_core/memory_broker.py +410 -0
  193. amb_core/models.py +141 -0
  194. amb_core/persistence.py +529 -0
  195. amb_core/schema.py +294 -0
  196. amb_core/tracing.py +358 -0
  197. atr/__init__.py +640 -0
  198. atr/access.py +348 -0
  199. atr/composition.py +645 -0
  200. atr/decorator.py +357 -0
  201. atr/executor.py +384 -0
  202. atr/health.py +557 -0
  203. atr/hf_utils.py +449 -0
  204. atr/injection.py +422 -0
  205. atr/metrics.py +440 -0
  206. atr/policies.py +403 -0
  207. atr/py.typed +2 -0
  208. atr/registry.py +452 -0
  209. atr/schema.py +480 -0
  210. atr/tools/safe/__init__.py +75 -0
  211. atr/tools/safe/calculator.py +467 -0
  212. atr/tools/safe/datetime_tool.py +443 -0
  213. atr/tools/safe/file_reader.py +402 -0
  214. atr/tools/safe/http_client.py +316 -0
  215. atr/tools/safe/json_parser.py +374 -0
  216. atr/tools/safe/text_tool.py +537 -0
  217. atr/tools/safe/toolkit.py +175 -0
  218. caas/__init__.py +162 -0
  219. caas/api/__init__.py +7 -0
  220. caas/api/server.py +1328 -0
  221. caas/caching.py +834 -0
  222. caas/cli.py +210 -0
  223. caas/conversation.py +223 -0
  224. caas/decay.py +72 -0
  225. caas/detection/__init__.py +9 -0
  226. caas/detection/detector.py +238 -0
  227. caas/enrichment.py +130 -0
  228. caas/gateway/__init__.py +27 -0
  229. caas/gateway/trust_gateway.py +474 -0
  230. caas/hf_utils.py +479 -0
  231. caas/ingestion/__init__.py +23 -0
  232. caas/ingestion/processors.py +253 -0
  233. caas/ingestion/structure_parser.py +188 -0
  234. caas/models.py +356 -0
  235. caas/pragmatic_truth.py +444 -0
  236. caas/routing/__init__.py +10 -0
  237. caas/routing/heuristic_router.py +58 -0
  238. caas/storage/__init__.py +9 -0
  239. caas/storage/store.py +389 -0
  240. caas/triad.py +213 -0
  241. caas/tuning/__init__.py +9 -0
  242. caas/tuning/tuner.py +329 -0
  243. caas/vfs/__init__.py +14 -0
  244. caas/vfs/filesystem.py +452 -0
  245. cmvk/__init__.py +218 -0
  246. cmvk/audit.py +402 -0
  247. cmvk/benchmarks.py +478 -0
  248. cmvk/constitutional.py +904 -0
  249. cmvk/hf_utils.py +301 -0
  250. cmvk/metrics.py +473 -0
  251. cmvk/profiles.py +300 -0
  252. cmvk/py.typed +0 -0
  253. cmvk/types.py +12 -0
  254. cmvk/verification.py +956 -0
  255. emk/__init__.py +89 -0
  256. emk/causal.py +352 -0
  257. emk/hf_utils.py +421 -0
  258. emk/indexer.py +83 -0
  259. emk/py.typed +0 -0
  260. emk/schema.py +204 -0
  261. emk/sleep_cycle.py +347 -0
  262. emk/store.py +281 -0
  263. iatp/__init__.py +166 -0
  264. iatp/attestation.py +461 -0
  265. iatp/cli.py +317 -0
  266. iatp/hf_utils.py +472 -0
  267. iatp/ipc_pipes.py +580 -0
  268. iatp/main.py +412 -0
  269. iatp/models/__init__.py +447 -0
  270. iatp/policy_engine.py +337 -0
  271. iatp/py.typed +2 -0
  272. iatp/recovery.py +321 -0
  273. iatp/security/__init__.py +270 -0
  274. iatp/sidecar/__init__.py +519 -0
  275. iatp/telemetry/__init__.py +164 -0
  276. iatp/tests/__init__.py +1 -0
  277. iatp/tests/test_attestation.py +370 -0
  278. iatp/tests/test_cli.py +131 -0
  279. iatp/tests/test_ed25519_attestation.py +211 -0
  280. iatp/tests/test_models.py +130 -0
  281. iatp/tests/test_policy_engine.py +347 -0
  282. iatp/tests/test_recovery.py +281 -0
  283. iatp/tests/test_security.py +222 -0
  284. iatp/tests/test_sidecar.py +167 -0
  285. iatp/tests/test_telemetry.py +175 -0
  286. mcp_kernel_server/__init__.py +28 -0
  287. mcp_kernel_server/cli.py +274 -0
  288. mcp_kernel_server/resources.py +217 -0
  289. mcp_kernel_server/server.py +564 -0
  290. mcp_kernel_server/tools.py +1174 -0
  291. mute_agent/__init__.py +68 -0
  292. mute_agent/core/__init__.py +1 -0
  293. mute_agent/core/execution_agent.py +166 -0
  294. mute_agent/core/handshake_protocol.py +201 -0
  295. mute_agent/core/reasoning_agent.py +238 -0
  296. mute_agent/knowledge_graph/__init__.py +1 -0
  297. mute_agent/knowledge_graph/graph_elements.py +65 -0
  298. mute_agent/knowledge_graph/multidimensional_graph.py +170 -0
  299. mute_agent/knowledge_graph/subgraph.py +224 -0
  300. mute_agent/listener/__init__.py +43 -0
  301. mute_agent/listener/adapters/__init__.py +31 -0
  302. mute_agent/listener/adapters/base_adapter.py +189 -0
  303. mute_agent/listener/adapters/caas_adapter.py +344 -0
  304. mute_agent/listener/adapters/control_plane_adapter.py +436 -0
  305. mute_agent/listener/adapters/iatp_adapter.py +332 -0
  306. mute_agent/listener/adapters/scak_adapter.py +251 -0
  307. mute_agent/listener/listener.py +610 -0
  308. mute_agent/listener/state_observer.py +436 -0
  309. mute_agent/listener/threshold_config.py +313 -0
  310. mute_agent/super_system/__init__.py +1 -0
  311. mute_agent/super_system/router.py +204 -0
  312. mute_agent/visualization/__init__.py +10 -0
  313. mute_agent/visualization/graph_debugger.py +502 -0
  314. nexus/README.md +60 -0
  315. nexus/__init__.py +51 -0
  316. nexus/arbiter.py +359 -0
  317. nexus/client.py +466 -0
  318. nexus/dmz.py +444 -0
  319. nexus/escrow.py +430 -0
  320. nexus/exceptions.py +286 -0
  321. nexus/pyproject.toml +36 -0
  322. nexus/registry.py +393 -0
  323. nexus/reputation.py +425 -0
  324. nexus/schemas/__init__.py +51 -0
  325. nexus/schemas/compliance.py +276 -0
  326. nexus/schemas/escrow.py +251 -0
  327. nexus/schemas/manifest.py +225 -0
  328. nexus/schemas/receipt.py +208 -0
  329. nexus/tests/__init__.py +0 -0
  330. nexus/tests/conftest.py +146 -0
  331. nexus/tests/test_arbiter.py +192 -0
  332. nexus/tests/test_dmz.py +194 -0
  333. nexus/tests/test_escrow.py +276 -0
  334. nexus/tests/test_exceptions.py +225 -0
  335. nexus/tests/test_registry.py +232 -0
  336. nexus/tests/test_reputation.py +328 -0
  337. nexus/tests/test_schemas.py +295 -0
@@ -0,0 +1,509 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """CloudEvents specification support for AMB.
4
+
5
+ This module provides CloudEvents v1.0 compatibility, enabling interoperability
6
+ with other systems that support the CNCF CloudEvents specification.
7
+
8
+ CloudEvents Spec: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md
9
+
10
+ Example:
11
+ from amb_core.cloudevents import CloudEvent, to_cloudevent, from_cloudevent
12
+
13
+ # Convert AMB Message to CloudEvent
14
+ message = Message(id="123", topic="fraud.alerts", payload={"risk": 0.9})
15
+ cloud_event = to_cloudevent(message, source="/agent-os/fraud-detector")
16
+
17
+ # Send as JSON (CloudEvents structured content mode)
18
+ json_data = cloud_event.to_json()
19
+
20
+ # Convert CloudEvent back to AMB Message
21
+ message = from_cloudevent(cloud_event)
22
+ """
23
+
24
+ from datetime import datetime, timezone
25
+ from typing import Any, Dict, Optional, Union
26
+ from pydantic import BaseModel, Field, field_validator, ConfigDict
27
+ import json
28
+ import uuid
29
+
30
+ from amb_core.models import Message, MessagePriority
31
+
32
+
33
+ # CloudEvents spec version
34
+ CLOUDEVENTS_SPEC_VERSION = "1.0"
35
+
36
+ # CloudEvents content type
37
+ CLOUDEVENTS_CONTENT_TYPE = "application/cloudevents+json"
38
+
39
+ # Agent OS event type prefix
40
+ AGENT_OS_TYPE_PREFIX = "dev.agent-os"
41
+
42
+
43
+ class CloudEvent(BaseModel):
44
+ """
45
+ CloudEvents v1.0 specification compliant event.
46
+
47
+ This model implements the CloudEvents specification required and optional attributes.
48
+ See: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md
49
+
50
+ Required Attributes:
51
+ - id: Unique identifier for the event
52
+ - source: Context in which the event happened (URI-reference)
53
+ - specversion: CloudEvents specification version
54
+ - type: Type of event (reverse-DNS naming recommended)
55
+
56
+ Optional Attributes:
57
+ - datacontenttype: Content type of data
58
+ - dataschema: Schema that data adheres to
59
+ - subject: Subject of the event in the context of the producer
60
+ - time: Timestamp of when the event happened
61
+ - data: Event payload
62
+
63
+ Extension Attributes (Agent OS specific):
64
+ - priority: Message priority (amb extension)
65
+ - traceid: Distributed trace ID (amb extension)
66
+ - spanid: Span ID for tracing (amb extension)
67
+ - parentspanid: Parent span ID (amb extension)
68
+ - ttl: Time-to-live in seconds (amb extension)
69
+ - sender: Sender identifier (amb extension)
70
+ - correlationid: Correlation ID for request-response (amb extension)
71
+ """
72
+
73
+ # Required attributes (CloudEvents spec)
74
+ id: str = Field(..., description="Unique identifier for the event")
75
+ source: str = Field(..., description="URI-reference identifying the context")
76
+ specversion: str = Field(default=CLOUDEVENTS_SPEC_VERSION, description="CloudEvents spec version")
77
+ type: str = Field(..., description="Event type (reverse-DNS naming)")
78
+
79
+ # Optional attributes (CloudEvents spec)
80
+ datacontenttype: Optional[str] = Field(
81
+ default="application/json",
82
+ description="Content type of the data attribute"
83
+ )
84
+ dataschema: Optional[str] = Field(
85
+ None,
86
+ description="URI identifying the schema that data adheres to"
87
+ )
88
+ subject: Optional[str] = Field(
89
+ None,
90
+ description="Subject of the event in the context of the event producer"
91
+ )
92
+ time: Optional[datetime] = Field(
93
+ default_factory=lambda: datetime.now(timezone.utc),
94
+ description="Timestamp of when the event happened (RFC 3339)"
95
+ )
96
+ data: Optional[Dict[str, Any]] = Field(
97
+ default_factory=dict,
98
+ description="Event payload"
99
+ )
100
+
101
+ # Extension attributes (Agent OS / AMB specific)
102
+ # Prefixed with 'amb' namespace per CloudEvents extension naming conventions
103
+ ambpriority: Optional[int] = Field(
104
+ None,
105
+ description="Message priority (AMB extension)"
106
+ )
107
+ ambtraceid: Optional[str] = Field(
108
+ None,
109
+ description="Distributed trace ID (AMB extension)"
110
+ )
111
+ ambspanid: Optional[str] = Field(
112
+ None,
113
+ description="Span ID within the trace (AMB extension)"
114
+ )
115
+ ambparentspanid: Optional[str] = Field(
116
+ None,
117
+ description="Parent span ID (AMB extension)"
118
+ )
119
+ ambttl: Optional[int] = Field(
120
+ None,
121
+ description="Time-to-live in seconds (AMB extension)"
122
+ )
123
+ ambsender: Optional[str] = Field(
124
+ None,
125
+ description="Sender identifier (AMB extension)"
126
+ )
127
+ ambcorrelationid: Optional[str] = Field(
128
+ None,
129
+ description="Correlation ID for request-response patterns (AMB extension)"
130
+ )
131
+ ambreplyto: Optional[str] = Field(
132
+ None,
133
+ description="Topic to reply to (AMB extension)"
134
+ )
135
+
136
+ model_config = ConfigDict(
137
+ json_encoders={
138
+ datetime: lambda v: v.isoformat() if v else None
139
+ },
140
+ extra="allow", # Allow additional extension attributes
141
+ )
142
+
143
+ @field_validator('specversion')
144
+ @classmethod
145
+ def validate_specversion(cls, v: str) -> str:
146
+ """Validate CloudEvents spec version."""
147
+ if v != CLOUDEVENTS_SPEC_VERSION:
148
+ raise ValueError(f"Unsupported specversion: {v}. Expected: {CLOUDEVENTS_SPEC_VERSION}")
149
+ return v
150
+
151
+ @field_validator('source')
152
+ @classmethod
153
+ def validate_source(cls, v: str) -> str:
154
+ """Validate source is a URI-reference."""
155
+ if not v:
156
+ raise ValueError("source cannot be empty")
157
+ return v
158
+
159
+ @field_validator('type')
160
+ @classmethod
161
+ def validate_type(cls, v: str) -> str:
162
+ """Validate type is non-empty."""
163
+ if not v:
164
+ raise ValueError("type cannot be empty")
165
+ return v
166
+
167
+ def to_json(self, **kwargs) -> str:
168
+ """
169
+ Serialize to CloudEvents JSON format (structured content mode).
170
+
171
+ Returns:
172
+ JSON string representation
173
+ """
174
+ return self.model_dump_json(exclude_none=True, **kwargs)
175
+
176
+ def to_dict(self) -> Dict[str, Any]:
177
+ """
178
+ Convert to dictionary (excludes None values).
179
+
180
+ Returns:
181
+ Dictionary representation
182
+ """
183
+ return self.model_dump(exclude_none=True)
184
+
185
+ @classmethod
186
+ def from_json(cls, json_str: str) -> "CloudEvent":
187
+ """
188
+ Parse from CloudEvents JSON format.
189
+
190
+ Args:
191
+ json_str: JSON string to parse
192
+
193
+ Returns:
194
+ CloudEvent instance
195
+ """
196
+ data = json.loads(json_str)
197
+ return cls.model_validate(data)
198
+
199
+ @classmethod
200
+ def from_dict(cls, data: Dict[str, Any]) -> "CloudEvent":
201
+ """
202
+ Create from dictionary.
203
+
204
+ Args:
205
+ data: Dictionary with CloudEvent attributes
206
+
207
+ Returns:
208
+ CloudEvent instance
209
+ """
210
+ return cls.model_validate(data)
211
+
212
+
213
+ def topic_to_type(topic: str, prefix: str = AGENT_OS_TYPE_PREFIX) -> str:
214
+ """
215
+ Convert an AMB topic to a CloudEvents type.
216
+
217
+ CloudEvents recommends reverse-DNS naming for types.
218
+
219
+ Args:
220
+ topic: AMB topic (e.g., "fraud.alerts")
221
+ prefix: Type prefix (default: "dev.agent-os")
222
+
223
+ Returns:
224
+ CloudEvents type (e.g., "dev.agent-os.fraud.alerts")
225
+
226
+ Example:
227
+ >>> topic_to_type("fraud.alerts")
228
+ "dev.agent-os.fraud.alerts"
229
+ """
230
+ return f"{prefix}.{topic}"
231
+
232
+
233
+ def type_to_topic(event_type: str, prefix: str = AGENT_OS_TYPE_PREFIX) -> str:
234
+ """
235
+ Convert a CloudEvents type back to an AMB topic.
236
+
237
+ Args:
238
+ event_type: CloudEvents type (e.g., "dev.agent-os.fraud.alerts")
239
+ prefix: Type prefix to strip (default: "dev.agent-os")
240
+
241
+ Returns:
242
+ AMB topic (e.g., "fraud.alerts")
243
+
244
+ Example:
245
+ >>> type_to_topic("dev.agent-os.fraud.alerts")
246
+ "fraud.alerts"
247
+ """
248
+ full_prefix = f"{prefix}."
249
+ if event_type.startswith(full_prefix):
250
+ return event_type[len(full_prefix):]
251
+ return event_type
252
+
253
+
254
+ def to_cloudevent(
255
+ message: Message,
256
+ source: str,
257
+ *,
258
+ type_prefix: str = AGENT_OS_TYPE_PREFIX,
259
+ dataschema: Optional[str] = None
260
+ ) -> CloudEvent:
261
+ """
262
+ Convert an AMB Message to a CloudEvent.
263
+
264
+ Args:
265
+ message: AMB Message to convert
266
+ source: CloudEvents source URI (identifies the event producer)
267
+ type_prefix: Prefix for the event type (default: "dev.agent-os")
268
+ dataschema: Optional URI of the data schema
269
+
270
+ Returns:
271
+ CloudEvent instance
272
+
273
+ Example:
274
+ message = Message(
275
+ id="msg-123",
276
+ topic="fraud.alerts",
277
+ payload={"transaction_id": "tx-456", "risk_score": 0.95},
278
+ priority=Priority.CRITICAL,
279
+ sender="fraud-detector"
280
+ )
281
+
282
+ event = to_cloudevent(message, source="/agent-os/fraud-detector")
283
+ # Result:
284
+ # {
285
+ # "specversion": "1.0",
286
+ # "id": "msg-123",
287
+ # "source": "/agent-os/fraud-detector",
288
+ # "type": "dev.agent-os.fraud.alerts",
289
+ # "datacontenttype": "application/json",
290
+ # "time": "2026-02-03T04:30:00Z",
291
+ # "data": {"transaction_id": "tx-456", "risk_score": 0.95},
292
+ # "ambpriority": 15,
293
+ # "ambsender": "fraud-detector"
294
+ # }
295
+ """
296
+ return CloudEvent(
297
+ id=message.id,
298
+ source=source,
299
+ type=topic_to_type(message.topic, type_prefix),
300
+ subject=message.topic, # Original topic as subject
301
+ time=message.timestamp,
302
+ data=message.payload,
303
+ dataschema=dataschema,
304
+
305
+ # AMB extensions
306
+ ambpriority=message.priority.value if message.priority else None,
307
+ ambtraceid=message.trace_id,
308
+ ambspanid=message.span_id,
309
+ ambparentspanid=message.parent_span_id,
310
+ ambttl=message.ttl,
311
+ ambsender=message.sender,
312
+ ambcorrelationid=message.correlation_id,
313
+ ambreplyto=message.reply_to,
314
+ )
315
+
316
+
317
+ def from_cloudevent(
318
+ event: CloudEvent,
319
+ *,
320
+ type_prefix: str = AGENT_OS_TYPE_PREFIX
321
+ ) -> Message:
322
+ """
323
+ Convert a CloudEvent to an AMB Message.
324
+
325
+ Args:
326
+ event: CloudEvent to convert
327
+ type_prefix: Prefix to strip from event type (default: "dev.agent-os")
328
+
329
+ Returns:
330
+ AMB Message instance
331
+
332
+ Example:
333
+ event = CloudEvent(
334
+ id="evt-123",
335
+ source="/external-system",
336
+ type="dev.agent-os.user.events",
337
+ data={"user_id": "u-456", "action": "login"}
338
+ )
339
+
340
+ message = from_cloudevent(event)
341
+ # message.topic == "user.events"
342
+ # message.payload == {"user_id": "u-456", "action": "login"}
343
+ """
344
+ # Determine topic from type or subject
345
+ topic = event.subject or type_to_topic(event.type, type_prefix)
346
+
347
+ # Map priority
348
+ priority = MessagePriority.NORMAL
349
+ if event.ambpriority is not None:
350
+ try:
351
+ priority = MessagePriority(event.ambpriority)
352
+ except ValueError:
353
+ # Use closest valid priority
354
+ if event.ambpriority >= MessagePriority.CRITICAL:
355
+ priority = MessagePriority.CRITICAL
356
+ elif event.ambpriority >= MessagePriority.URGENT:
357
+ priority = MessagePriority.URGENT
358
+ elif event.ambpriority >= MessagePriority.HIGH:
359
+ priority = MessagePriority.HIGH
360
+ elif event.ambpriority >= MessagePriority.NORMAL:
361
+ priority = MessagePriority.NORMAL
362
+ elif event.ambpriority >= MessagePriority.LOW:
363
+ priority = MessagePriority.LOW
364
+ else:
365
+ priority = MessagePriority.BACKGROUND
366
+
367
+ return Message(
368
+ id=event.id,
369
+ topic=topic,
370
+ payload=event.data or {},
371
+ priority=priority,
372
+ timestamp=event.time or datetime.now(timezone.utc),
373
+ sender=event.ambsender,
374
+ correlation_id=event.ambcorrelationid,
375
+ reply_to=event.ambreplyto,
376
+ ttl=event.ambttl,
377
+ trace_id=event.ambtraceid,
378
+ span_id=event.ambspanid,
379
+ parent_span_id=event.ambparentspanid,
380
+ metadata={
381
+ "cloudevents.source": event.source,
382
+ "cloudevents.type": event.type,
383
+ "cloudevents.dataschema": event.dataschema,
384
+ }
385
+ )
386
+
387
+
388
+ class CloudEventBatch(BaseModel):
389
+ """
390
+ Batch of CloudEvents for bulk transmission.
391
+
392
+ CloudEvents batching spec: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/json-format.md#4-json-batch-format
393
+ """
394
+
395
+ events: list[CloudEvent] = Field(default_factory=list)
396
+
397
+ def to_json(self) -> str:
398
+ """Serialize batch to JSON array."""
399
+ def serialize_event(e: CloudEvent) -> Dict[str, Any]:
400
+ d = e.to_dict()
401
+ # Convert datetime to ISO format
402
+ if "time" in d and isinstance(d["time"], datetime):
403
+ d["time"] = d["time"].isoformat()
404
+ return d
405
+
406
+ return json.dumps([serialize_event(e) for e in self.events])
407
+
408
+ @classmethod
409
+ def from_json(cls, json_str: str) -> "CloudEventBatch":
410
+ """Parse batch from JSON array."""
411
+ data = json.loads(json_str)
412
+ events = [CloudEvent.from_dict(e) for e in data]
413
+ return cls(events=events)
414
+
415
+ def __len__(self) -> int:
416
+ return len(self.events)
417
+
418
+ def __iter__(self):
419
+ return iter(self.events)
420
+
421
+
422
+ # HTTP binding headers for CloudEvents
423
+ # See: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/http-protocol-binding.md
424
+ HTTP_HEADERS = {
425
+ "id": "ce-id",
426
+ "source": "ce-source",
427
+ "specversion": "ce-specversion",
428
+ "type": "ce-type",
429
+ "datacontenttype": "content-type",
430
+ "dataschema": "ce-dataschema",
431
+ "subject": "ce-subject",
432
+ "time": "ce-time",
433
+ # AMB extensions
434
+ "ambpriority": "ce-ambpriority",
435
+ "ambtraceid": "ce-ambtraceid",
436
+ "ambspanid": "ce-ambspanid",
437
+ "ambparentspanid": "ce-ambparentspanid",
438
+ "ambttl": "ce-ambttl",
439
+ "ambsender": "ce-ambsender",
440
+ "ambcorrelationid": "ce-ambcorrelationid",
441
+ "ambreplyto": "ce-ambreplyto",
442
+ }
443
+
444
+
445
+ def to_http_headers(event: CloudEvent) -> Dict[str, str]:
446
+ """
447
+ Convert CloudEvent to HTTP headers (binary content mode).
448
+
449
+ Args:
450
+ event: CloudEvent to convert
451
+
452
+ Returns:
453
+ Dictionary of HTTP headers
454
+
455
+ Example:
456
+ headers = to_http_headers(event)
457
+ # {
458
+ # "ce-id": "msg-123",
459
+ # "ce-source": "/agent-os/detector",
460
+ # "ce-type": "dev.agent-os.fraud.alerts",
461
+ # "ce-specversion": "1.0",
462
+ # "content-type": "application/json",
463
+ # ...
464
+ # }
465
+ """
466
+ headers = {}
467
+ event_dict = event.to_dict()
468
+
469
+ for attr, header in HTTP_HEADERS.items():
470
+ if attr in event_dict and event_dict[attr] is not None:
471
+ value = event_dict[attr]
472
+ if isinstance(value, datetime):
473
+ value = value.isoformat()
474
+ elif not isinstance(value, str):
475
+ value = str(value)
476
+ headers[header] = value
477
+
478
+ return headers
479
+
480
+
481
+ def from_http_headers(headers: Dict[str, str], data: Optional[Dict[str, Any]] = None) -> CloudEvent:
482
+ """
483
+ Create CloudEvent from HTTP headers (binary content mode).
484
+
485
+ Args:
486
+ headers: HTTP headers (case-insensitive)
487
+ data: Request body as parsed JSON
488
+
489
+ Returns:
490
+ CloudEvent instance
491
+ """
492
+ # Normalize header names to lowercase
493
+ normalized = {k.lower(): v for k, v in headers.items()}
494
+
495
+ # Reverse mapping
496
+ header_to_attr = {v.lower(): k for k, v in HTTP_HEADERS.items()}
497
+
498
+ event_data = {}
499
+ for header, value in normalized.items():
500
+ if header in header_to_attr:
501
+ attr = header_to_attr[header]
502
+ # Convert types as needed
503
+ if attr in ("ambpriority", "ambttl"):
504
+ value = int(value)
505
+ event_data[attr] = value
506
+
507
+ event_data["data"] = data
508
+
509
+ return CloudEvent.from_dict(event_data)