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,376 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """AWS SQS broker adapter for AMB.
4
+
5
+ Amazon SQS provides fully managed message queues for microservices,
6
+ distributed systems, and serverless applications.
7
+ """
8
+
9
+ import asyncio
10
+ import json
11
+ import uuid
12
+ from typing import Dict, List, Optional
13
+
14
+ from amb_core.broker import BrokerAdapter, MessageHandler
15
+ from amb_core.models import Message
16
+
17
+ try:
18
+ import aioboto3
19
+ from botocore.exceptions import ClientError
20
+ except ImportError:
21
+ raise ImportError(
22
+ "AWS SQS adapter requires 'aioboto3' package. "
23
+ "Install it with: pip install amb-core[aws]"
24
+ )
25
+
26
+
27
+ class AWSSQSBroker(BrokerAdapter):
28
+ """
29
+ AWS SQS broker adapter.
30
+
31
+ This adapter uses AWS SQS queues for reliable message delivery.
32
+ Supports both standard queues and FIFO queues for ordered processing.
33
+
34
+ Example:
35
+ ```python
36
+ from amb_core.adapters import AWSSQSBroker
37
+
38
+ broker = AWSSQSBroker(
39
+ region_name="us-east-1",
40
+ queue_url="https://sqs.us-east-1.amazonaws.com/123456789/my-queue"
41
+ )
42
+ await broker.connect()
43
+
44
+ # Subscribe
45
+ async def handler(msg):
46
+ print(f"Received: {msg.payload}")
47
+
48
+ await broker.subscribe("agent.tasks", handler)
49
+
50
+ # Publish
51
+ await broker.publish(Message(topic="agent.tasks", payload={"task": "analyze"}))
52
+ ```
53
+ """
54
+
55
+ def __init__(
56
+ self,
57
+ region_name: str = "us-east-1",
58
+ queue_url: Optional[str] = None,
59
+ queue_name: str = "amb-messages",
60
+ use_fifo: bool = False,
61
+ aws_access_key_id: Optional[str] = None,
62
+ aws_secret_access_key: Optional[str] = None
63
+ ):
64
+ """
65
+ Initialize AWS SQS broker.
66
+
67
+ Args:
68
+ region_name: AWS region
69
+ queue_url: Existing queue URL (optional)
70
+ queue_name: Queue name to create/use
71
+ use_fifo: Use FIFO queue for ordered delivery
72
+ aws_access_key_id: AWS access key (uses env vars if not provided)
73
+ aws_secret_access_key: AWS secret key (uses env vars if not provided)
74
+ """
75
+ self.region_name = region_name
76
+ self.queue_url = queue_url
77
+ self.queue_name = queue_name
78
+ self.use_fifo = use_fifo
79
+ self.aws_access_key_id = aws_access_key_id
80
+ self.aws_secret_access_key = aws_secret_access_key
81
+
82
+ self._session = None
83
+ self._sqs = None
84
+ self._subscriptions: Dict[str, str] = {} # subscription_id -> topic
85
+ self._handlers: Dict[str, MessageHandler] = {}
86
+ self._tasks: set = set()
87
+ self._running = False
88
+ self._topic_queues: Dict[str, str] = {} # topic -> queue_url
89
+
90
+ async def connect(self) -> None:
91
+ """Connect to AWS SQS."""
92
+ self._session = aioboto3.Session(
93
+ aws_access_key_id=self.aws_access_key_id,
94
+ aws_secret_access_key=self.aws_secret_access_key,
95
+ region_name=self.region_name
96
+ )
97
+
98
+ self._running = True
99
+
100
+ # Get or create main queue
101
+ async with self._session.client('sqs') as sqs:
102
+ if not self.queue_url:
103
+ queue_name = f"{self.queue_name}.fifo" if self.use_fifo else self.queue_name
104
+
105
+ try:
106
+ # Try to get existing queue
107
+ response = await sqs.get_queue_url(QueueName=queue_name)
108
+ self.queue_url = response['QueueUrl']
109
+ except ClientError:
110
+ # Create new queue
111
+ attributes = {}
112
+ if self.use_fifo:
113
+ attributes['FifoQueue'] = 'true'
114
+ attributes['ContentBasedDeduplication'] = 'true'
115
+
116
+ response = await sqs.create_queue(
117
+ QueueName=queue_name,
118
+ Attributes=attributes
119
+ )
120
+ self.queue_url = response['QueueUrl']
121
+
122
+ self._topic_queues['default'] = self.queue_url
123
+
124
+ async def disconnect(self) -> None:
125
+ """Disconnect from AWS SQS."""
126
+ self._running = False
127
+
128
+ # Cancel all tasks
129
+ for task in self._tasks:
130
+ if not task.done():
131
+ task.cancel()
132
+
133
+ if self._tasks:
134
+ await asyncio.gather(*self._tasks, return_exceptions=True)
135
+
136
+ self._tasks.clear()
137
+ self._session = None
138
+
139
+ async def publish(self, message: Message, wait_for_confirmation: bool = False) -> Optional[str]:
140
+ """
141
+ Publish message to SQS queue.
142
+
143
+ Args:
144
+ message: Message to publish
145
+ wait_for_confirmation: Wait for SQS acknowledgment (always true for SQS)
146
+
147
+ Returns:
148
+ Message ID
149
+ """
150
+ if not self._session:
151
+ raise ConnectionError("Not connected to AWS SQS")
152
+
153
+ async with self._session.client('sqs') as sqs:
154
+ # Serialize message
155
+ message_body = message.model_dump_json()
156
+
157
+ # Build send parameters
158
+ params = {
159
+ 'QueueUrl': self.queue_url,
160
+ 'MessageBody': message_body,
161
+ 'MessageAttributes': {
162
+ 'topic': {
163
+ 'DataType': 'String',
164
+ 'StringValue': message.topic
165
+ },
166
+ 'source': {
167
+ 'DataType': 'String',
168
+ 'StringValue': message.source
169
+ },
170
+ 'message_id': {
171
+ 'DataType': 'String',
172
+ 'StringValue': message.id
173
+ }
174
+ }
175
+ }
176
+
177
+ # FIFO queues require message group ID
178
+ if self.use_fifo:
179
+ params['MessageGroupId'] = message.topic.replace('/', '-')
180
+ params['MessageDeduplicationId'] = message.id
181
+
182
+ # Send message
183
+ response = await sqs.send_message(**params)
184
+
185
+ return response.get('MessageId', message.id)
186
+
187
+ async def subscribe(self, topic: str, handler: MessageHandler) -> str:
188
+ """
189
+ Subscribe to messages on a topic.
190
+
191
+ Starts polling the SQS queue for messages matching the topic.
192
+
193
+ Args:
194
+ topic: Topic to filter messages by
195
+ handler: Message handler
196
+
197
+ Returns:
198
+ Subscription ID
199
+ """
200
+ subscription_id = str(uuid.uuid4())
201
+
202
+ self._subscriptions[subscription_id] = topic
203
+ self._handlers[topic] = handler
204
+
205
+ # Start polling task
206
+ task = asyncio.create_task(self._poll_task(subscription_id, topic, handler))
207
+ self._tasks.add(task)
208
+ task.add_done_callback(self._tasks.discard)
209
+
210
+ return subscription_id
211
+
212
+ async def _poll_task(self, subscription_id: str, topic: str, handler: MessageHandler):
213
+ """Poll SQS queue for messages."""
214
+ while self._running and subscription_id in self._subscriptions:
215
+ try:
216
+ async with self._session.client('sqs') as sqs:
217
+ # Receive messages
218
+ response = await sqs.receive_message(
219
+ QueueUrl=self.queue_url,
220
+ MaxNumberOfMessages=10,
221
+ WaitTimeSeconds=20, # Long polling
222
+ MessageAttributeNames=['All']
223
+ )
224
+
225
+ messages = response.get('Messages', [])
226
+
227
+ for sqs_message in messages:
228
+ try:
229
+ # Parse message
230
+ body = sqs_message['Body']
231
+ amb_message = Message.model_validate_json(body)
232
+
233
+ # Check topic filter
234
+ if amb_message.topic == topic or topic == "*":
235
+ await handler(amb_message)
236
+
237
+ # Delete message after processing
238
+ await sqs.delete_message(
239
+ QueueUrl=self.queue_url,
240
+ ReceiptHandle=sqs_message['ReceiptHandle']
241
+ )
242
+
243
+ except Exception as e:
244
+ print(f"Error handling SQS message: {e}")
245
+ # Leave message in queue for retry
246
+
247
+ except asyncio.CancelledError:
248
+ break
249
+ except Exception as e:
250
+ print(f"Error polling SQS: {e}")
251
+ await asyncio.sleep(1.0)
252
+
253
+ async def unsubscribe(self, subscription_id: str) -> None:
254
+ """
255
+ Unsubscribe from messages.
256
+
257
+ Args:
258
+ subscription_id: Subscription ID
259
+ """
260
+ if subscription_id in self._subscriptions:
261
+ topic = self._subscriptions[subscription_id]
262
+ del self._subscriptions[subscription_id]
263
+
264
+ if topic in self._handlers:
265
+ del self._handlers[topic]
266
+
267
+ async def request(self, message: Message, timeout: float = 30.0) -> Message:
268
+ """
269
+ Send request and wait for response.
270
+
271
+ Uses a temporary response queue for the request-response pattern.
272
+
273
+ Args:
274
+ message: Request message
275
+ timeout: Timeout in seconds
276
+
277
+ Returns:
278
+ Response message
279
+ """
280
+ if not self._session:
281
+ raise ConnectionError("Not connected to AWS SQS")
282
+
283
+ # Generate correlation ID
284
+ if not message.correlation_id:
285
+ message.correlation_id = str(uuid.uuid4())
286
+
287
+ # Create response queue
288
+ response_queue: asyncio.Queue = asyncio.Queue()
289
+
290
+ async def response_handler(msg: Message):
291
+ if msg.correlation_id == message.correlation_id:
292
+ await response_queue.put(msg)
293
+
294
+ # Subscribe to responses (using correlation ID as topic filter)
295
+ response_topic = f"response.{message.correlation_id}"
296
+ sub_id = await self.subscribe(response_topic, response_handler)
297
+
298
+ try:
299
+ # Set reply-to
300
+ message.reply_to = response_topic
301
+
302
+ # Publish request
303
+ await self.publish(message, wait_for_confirmation=False)
304
+
305
+ # Wait for response
306
+ try:
307
+ response = await asyncio.wait_for(response_queue.get(), timeout=timeout)
308
+ return response
309
+ except asyncio.TimeoutError:
310
+ raise TimeoutError(f"No response received within {timeout} seconds")
311
+
312
+ finally:
313
+ await self.unsubscribe(sub_id)
314
+
315
+ async def get_pending_messages(self, topic: str, limit: int = 10) -> List[Message]:
316
+ """
317
+ Peek at pending messages in the queue.
318
+
319
+ Note: SQS doesn't support true peeking, so this uses visibility timeout
320
+ and then returns messages to the queue.
321
+
322
+ Args:
323
+ topic: Topic to filter by
324
+ limit: Maximum messages to retrieve
325
+
326
+ Returns:
327
+ List of messages
328
+ """
329
+ if not self._session:
330
+ raise ConnectionError("Not connected to AWS SQS")
331
+
332
+ messages = []
333
+
334
+ async with self._session.client('sqs') as sqs:
335
+ # Receive with short visibility timeout
336
+ response = await sqs.receive_message(
337
+ QueueUrl=self.queue_url,
338
+ MaxNumberOfMessages=min(limit, 10),
339
+ VisibilityTimeout=1, # Short timeout so messages return to queue
340
+ MessageAttributeNames=['All']
341
+ )
342
+
343
+ for sqs_message in response.get('Messages', []):
344
+ try:
345
+ body = sqs_message['Body']
346
+ amb_message = Message.model_validate_json(body)
347
+
348
+ if amb_message.topic == topic or topic == "*":
349
+ messages.append(amb_message)
350
+ except Exception:
351
+ continue
352
+
353
+ return messages
354
+
355
+ async def health_check(self) -> bool:
356
+ """Check if connected to AWS SQS."""
357
+ if not self._session:
358
+ return False
359
+
360
+ try:
361
+ async with self._session.client('sqs') as sqs:
362
+ await sqs.get_queue_attributes(
363
+ QueueUrl=self.queue_url,
364
+ AttributeNames=['QueueArn']
365
+ )
366
+ return True
367
+ except Exception:
368
+ return False
369
+
370
+ async def purge_queue(self) -> None:
371
+ """Purge all messages from the queue."""
372
+ if not self._session:
373
+ raise ConnectionError("Not connected to AWS SQS")
374
+
375
+ async with self._session.client('sqs') as sqs:
376
+ await sqs.purge_queue(QueueUrl=self.queue_url)