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.
- agent_control_plane/__init__.py +662 -0
- agent_control_plane/a2a_adapter.py +543 -0
- agent_control_plane/adapter.py +417 -0
- agent_control_plane/agent_hibernation.py +394 -0
- agent_control_plane/agent_kernel.py +470 -0
- agent_control_plane/compliance.py +720 -0
- agent_control_plane/constraint_graphs.py +478 -0
- agent_control_plane/control_plane.py +854 -0
- agent_control_plane/example_executors.py +195 -0
- agent_control_plane/execution_engine.py +231 -0
- agent_control_plane/flight_recorder.py +846 -0
- agent_control_plane/governance_layer.py +435 -0
- agent_control_plane/hf_utils.py +563 -0
- agent_control_plane/interfaces/__init__.py +55 -0
- agent_control_plane/interfaces/kernel_interface.py +361 -0
- agent_control_plane/interfaces/plugin_interface.py +497 -0
- agent_control_plane/interfaces/protocol_interfaces.py +387 -0
- agent_control_plane/kernel_space.py +1009 -0
- agent_control_plane/langchain_adapter.py +424 -0
- agent_control_plane/lifecycle.py +3113 -0
- agent_control_plane/mcp_adapter.py +653 -0
- agent_control_plane/ml_safety.py +563 -0
- agent_control_plane/multimodal.py +727 -0
- agent_control_plane/mute_agent.py +422 -0
- agent_control_plane/observability.py +787 -0
- agent_control_plane/orchestrator.py +482 -0
- agent_control_plane/plugin_registry.py +750 -0
- agent_control_plane/policy_engine.py +954 -0
- agent_control_plane/process_isolation.py +777 -0
- agent_control_plane/shadow_mode.py +310 -0
- agent_control_plane/signals.py +493 -0
- agent_control_plane/supervisor_agents.py +430 -0
- agent_control_plane/time_travel_debugger.py +557 -0
- agent_control_plane/tool_registry.py +452 -0
- agent_control_plane/vfs.py +697 -0
- agent_kernel/__init__.py +69 -0
- agent_kernel/analyzer.py +435 -0
- agent_kernel/auditor.py +36 -0
- agent_kernel/completeness_auditor.py +237 -0
- agent_kernel/detector.py +203 -0
- agent_kernel/kernel.py +744 -0
- agent_kernel/memory_manager.py +85 -0
- agent_kernel/models.py +374 -0
- agent_kernel/nudge_mechanism.py +263 -0
- agent_kernel/outcome_analyzer.py +338 -0
- agent_kernel/patcher.py +582 -0
- agent_kernel/semantic_analyzer.py +316 -0
- agent_kernel/semantic_purge.py +349 -0
- agent_kernel/simulator.py +449 -0
- agent_kernel/teacher.py +85 -0
- agent_kernel/triage.py +152 -0
- agent_os/__init__.py +409 -0
- agent_os/_adversarial_impl.py +200 -0
- agent_os/_circuit_breaker_impl.py +232 -0
- agent_os/_mcp_metrics.py +193 -0
- agent_os/adversarial.py +20 -0
- agent_os/agents_compat.py +490 -0
- agent_os/audit_logger.py +135 -0
- agent_os/base_agent.py +651 -0
- agent_os/circuit_breaker.py +34 -0
- agent_os/cli/__init__.py +659 -0
- agent_os/cli/cmd_audit.py +128 -0
- agent_os/cli/cmd_init.py +152 -0
- agent_os/cli/cmd_policy.py +41 -0
- agent_os/cli/cmd_policy_gen.py +180 -0
- agent_os/cli/cmd_validate.py +258 -0
- agent_os/cli/mcp_scan.py +265 -0
- agent_os/cli/output.py +192 -0
- agent_os/cli/policy_checker.py +330 -0
- agent_os/compat.py +74 -0
- agent_os/constraint_graph.py +234 -0
- agent_os/content_governance.py +140 -0
- agent_os/context_budget.py +305 -0
- agent_os/credential_redactor.py +224 -0
- agent_os/diff_policy.py +89 -0
- agent_os/egress_policy.py +159 -0
- agent_os/escalation.py +276 -0
- agent_os/event_bus.py +124 -0
- agent_os/exceptions.py +180 -0
- agent_os/execution_context_policy.py +141 -0
- agent_os/github_enterprise.py +96 -0
- agent_os/health.py +20 -0
- agent_os/integrations/__init__.py +279 -0
- agent_os/integrations/a2a_adapter.py +279 -0
- agent_os/integrations/agent_lightning/__init__.py +30 -0
- agent_os/integrations/anthropic_adapter.py +420 -0
- agent_os/integrations/autogen_adapter.py +620 -0
- agent_os/integrations/base.py +1137 -0
- agent_os/integrations/compat.py +229 -0
- agent_os/integrations/config.py +98 -0
- agent_os/integrations/conversation_guardian.py +957 -0
- agent_os/integrations/crewai_adapter.py +467 -0
- agent_os/integrations/drift_detector.py +425 -0
- agent_os/integrations/dry_run.py +124 -0
- agent_os/integrations/escalation.py +582 -0
- agent_os/integrations/gemini_adapter.py +364 -0
- agent_os/integrations/google_adk_adapter.py +633 -0
- agent_os/integrations/guardrails_adapter.py +394 -0
- agent_os/integrations/health.py +197 -0
- agent_os/integrations/langchain_adapter.py +654 -0
- agent_os/integrations/llamafirewall.py +343 -0
- agent_os/integrations/llamaindex_adapter.py +188 -0
- agent_os/integrations/logging.py +191 -0
- agent_os/integrations/maf_adapter.py +631 -0
- agent_os/integrations/mistral_adapter.py +365 -0
- agent_os/integrations/openai_adapter.py +816 -0
- agent_os/integrations/openai_agents_sdk.py +406 -0
- agent_os/integrations/policy_compose.py +171 -0
- agent_os/integrations/profiling.py +144 -0
- agent_os/integrations/pydantic_ai_adapter.py +420 -0
- agent_os/integrations/rate_limiter.py +130 -0
- agent_os/integrations/rbac.py +143 -0
- agent_os/integrations/registry.py +113 -0
- agent_os/integrations/scope_guard.py +303 -0
- agent_os/integrations/semantic_kernel_adapter.py +769 -0
- agent_os/integrations/smolagents_adapter.py +629 -0
- agent_os/integrations/templates.py +178 -0
- agent_os/integrations/token_budget.py +134 -0
- agent_os/integrations/tool_aliases.py +190 -0
- agent_os/integrations/webhooks.py +177 -0
- agent_os/lite.py +208 -0
- agent_os/mcp_gateway.py +385 -0
- agent_os/mcp_message_signer.py +273 -0
- agent_os/mcp_protocols.py +161 -0
- agent_os/mcp_response_scanner.py +232 -0
- agent_os/mcp_security.py +924 -0
- agent_os/mcp_session_auth.py +231 -0
- agent_os/mcp_sliding_rate_limiter.py +184 -0
- agent_os/memory_guard.py +409 -0
- agent_os/metrics.py +134 -0
- agent_os/mute.py +428 -0
- agent_os/mute_agent.py +209 -0
- agent_os/policies/__init__.py +77 -0
- agent_os/policies/async_evaluator.py +275 -0
- agent_os/policies/backends.py +670 -0
- agent_os/policies/bridge.py +169 -0
- agent_os/policies/budget.py +85 -0
- agent_os/policies/cli.py +294 -0
- agent_os/policies/conflict_resolution.py +270 -0
- agent_os/policies/data_classification.py +252 -0
- agent_os/policies/evaluator.py +239 -0
- agent_os/policies/policy_schema.json +228 -0
- agent_os/policies/rate_limiting.py +145 -0
- agent_os/policies/schema.py +115 -0
- agent_os/policies/shared.py +331 -0
- agent_os/prompt_injection.py +694 -0
- agent_os/providers.py +182 -0
- agent_os/py.typed +0 -0
- agent_os/retry.py +81 -0
- agent_os/reversibility.py +251 -0
- agent_os/sandbox.py +432 -0
- agent_os/sandbox_provider.py +140 -0
- agent_os/secure_codegen.py +525 -0
- agent_os/security_skills.py +538 -0
- agent_os/semantic_policy.py +422 -0
- agent_os/server/__init__.py +15 -0
- agent_os/server/__main__.py +25 -0
- agent_os/server/app.py +277 -0
- agent_os/server/models.py +104 -0
- agent_os/shift_left_metrics.py +130 -0
- agent_os/stateless.py +742 -0
- agent_os/supervisor.py +148 -0
- agent_os/task_outcome.py +148 -0
- agent_os/transparency.py +181 -0
- agent_os/trust_root.py +128 -0
- agent_os_kernel-3.1.0.dist-info/METADATA +1269 -0
- agent_os_kernel-3.1.0.dist-info/RECORD +337 -0
- agent_os_kernel-3.1.0.dist-info/WHEEL +4 -0
- agent_os_kernel-3.1.0.dist-info/entry_points.txt +2 -0
- agent_os_kernel-3.1.0.dist-info/licenses/LICENSE +21 -0
- agent_os_observability/__init__.py +27 -0
- agent_os_observability/dashboards.py +898 -0
- agent_os_observability/metrics.py +398 -0
- agent_os_observability/server.py +223 -0
- agent_os_observability/tracer.py +232 -0
- agent_primitives/__init__.py +24 -0
- agent_primitives/failures.py +84 -0
- agent_primitives/py.typed +0 -0
- amb_core/__init__.py +177 -0
- amb_core/adapters/__init__.py +57 -0
- amb_core/adapters/aws_sqs_broker.py +376 -0
- amb_core/adapters/azure_servicebus_broker.py +340 -0
- amb_core/adapters/kafka_broker.py +260 -0
- amb_core/adapters/nats_broker.py +285 -0
- amb_core/adapters/rabbitmq_broker.py +235 -0
- amb_core/adapters/redis_broker.py +262 -0
- amb_core/broker.py +145 -0
- amb_core/bus.py +481 -0
- amb_core/cloudevents.py +509 -0
- amb_core/dlq.py +345 -0
- amb_core/hf_utils.py +536 -0
- amb_core/memory_broker.py +410 -0
- amb_core/models.py +141 -0
- amb_core/persistence.py +529 -0
- amb_core/schema.py +294 -0
- amb_core/tracing.py +358 -0
- atr/__init__.py +640 -0
- atr/access.py +348 -0
- atr/composition.py +645 -0
- atr/decorator.py +357 -0
- atr/executor.py +384 -0
- atr/health.py +557 -0
- atr/hf_utils.py +449 -0
- atr/injection.py +422 -0
- atr/metrics.py +440 -0
- atr/policies.py +403 -0
- atr/py.typed +2 -0
- atr/registry.py +452 -0
- atr/schema.py +480 -0
- atr/tools/safe/__init__.py +75 -0
- atr/tools/safe/calculator.py +467 -0
- atr/tools/safe/datetime_tool.py +443 -0
- atr/tools/safe/file_reader.py +402 -0
- atr/tools/safe/http_client.py +316 -0
- atr/tools/safe/json_parser.py +374 -0
- atr/tools/safe/text_tool.py +537 -0
- atr/tools/safe/toolkit.py +175 -0
- caas/__init__.py +162 -0
- caas/api/__init__.py +7 -0
- caas/api/server.py +1328 -0
- caas/caching.py +834 -0
- caas/cli.py +210 -0
- caas/conversation.py +223 -0
- caas/decay.py +72 -0
- caas/detection/__init__.py +9 -0
- caas/detection/detector.py +238 -0
- caas/enrichment.py +130 -0
- caas/gateway/__init__.py +27 -0
- caas/gateway/trust_gateway.py +474 -0
- caas/hf_utils.py +479 -0
- caas/ingestion/__init__.py +23 -0
- caas/ingestion/processors.py +253 -0
- caas/ingestion/structure_parser.py +188 -0
- caas/models.py +356 -0
- caas/pragmatic_truth.py +444 -0
- caas/routing/__init__.py +10 -0
- caas/routing/heuristic_router.py +58 -0
- caas/storage/__init__.py +9 -0
- caas/storage/store.py +389 -0
- caas/triad.py +213 -0
- caas/tuning/__init__.py +9 -0
- caas/tuning/tuner.py +329 -0
- caas/vfs/__init__.py +14 -0
- caas/vfs/filesystem.py +452 -0
- cmvk/__init__.py +218 -0
- cmvk/audit.py +402 -0
- cmvk/benchmarks.py +478 -0
- cmvk/constitutional.py +904 -0
- cmvk/hf_utils.py +301 -0
- cmvk/metrics.py +473 -0
- cmvk/profiles.py +300 -0
- cmvk/py.typed +0 -0
- cmvk/types.py +12 -0
- cmvk/verification.py +956 -0
- emk/__init__.py +89 -0
- emk/causal.py +352 -0
- emk/hf_utils.py +421 -0
- emk/indexer.py +83 -0
- emk/py.typed +0 -0
- emk/schema.py +204 -0
- emk/sleep_cycle.py +347 -0
- emk/store.py +281 -0
- iatp/__init__.py +166 -0
- iatp/attestation.py +461 -0
- iatp/cli.py +317 -0
- iatp/hf_utils.py +472 -0
- iatp/ipc_pipes.py +580 -0
- iatp/main.py +412 -0
- iatp/models/__init__.py +447 -0
- iatp/policy_engine.py +337 -0
- iatp/py.typed +2 -0
- iatp/recovery.py +321 -0
- iatp/security/__init__.py +270 -0
- iatp/sidecar/__init__.py +519 -0
- iatp/telemetry/__init__.py +164 -0
- iatp/tests/__init__.py +1 -0
- iatp/tests/test_attestation.py +370 -0
- iatp/tests/test_cli.py +131 -0
- iatp/tests/test_ed25519_attestation.py +211 -0
- iatp/tests/test_models.py +130 -0
- iatp/tests/test_policy_engine.py +347 -0
- iatp/tests/test_recovery.py +281 -0
- iatp/tests/test_security.py +222 -0
- iatp/tests/test_sidecar.py +167 -0
- iatp/tests/test_telemetry.py +175 -0
- mcp_kernel_server/__init__.py +28 -0
- mcp_kernel_server/cli.py +274 -0
- mcp_kernel_server/resources.py +217 -0
- mcp_kernel_server/server.py +564 -0
- mcp_kernel_server/tools.py +1174 -0
- mute_agent/__init__.py +68 -0
- mute_agent/core/__init__.py +1 -0
- mute_agent/core/execution_agent.py +166 -0
- mute_agent/core/handshake_protocol.py +201 -0
- mute_agent/core/reasoning_agent.py +238 -0
- mute_agent/knowledge_graph/__init__.py +1 -0
- mute_agent/knowledge_graph/graph_elements.py +65 -0
- mute_agent/knowledge_graph/multidimensional_graph.py +170 -0
- mute_agent/knowledge_graph/subgraph.py +224 -0
- mute_agent/listener/__init__.py +43 -0
- mute_agent/listener/adapters/__init__.py +31 -0
- mute_agent/listener/adapters/base_adapter.py +189 -0
- mute_agent/listener/adapters/caas_adapter.py +344 -0
- mute_agent/listener/adapters/control_plane_adapter.py +436 -0
- mute_agent/listener/adapters/iatp_adapter.py +332 -0
- mute_agent/listener/adapters/scak_adapter.py +251 -0
- mute_agent/listener/listener.py +610 -0
- mute_agent/listener/state_observer.py +436 -0
- mute_agent/listener/threshold_config.py +313 -0
- mute_agent/super_system/__init__.py +1 -0
- mute_agent/super_system/router.py +204 -0
- mute_agent/visualization/__init__.py +10 -0
- mute_agent/visualization/graph_debugger.py +502 -0
- nexus/README.md +60 -0
- nexus/__init__.py +51 -0
- nexus/arbiter.py +359 -0
- nexus/client.py +466 -0
- nexus/dmz.py +444 -0
- nexus/escrow.py +430 -0
- nexus/exceptions.py +286 -0
- nexus/pyproject.toml +36 -0
- nexus/registry.py +393 -0
- nexus/reputation.py +425 -0
- nexus/schemas/__init__.py +51 -0
- nexus/schemas/compliance.py +276 -0
- nexus/schemas/escrow.py +251 -0
- nexus/schemas/manifest.py +225 -0
- nexus/schemas/receipt.py +208 -0
- nexus/tests/__init__.py +0 -0
- nexus/tests/conftest.py +146 -0
- nexus/tests/test_arbiter.py +192 -0
- nexus/tests/test_dmz.py +194 -0
- nexus/tests/test_escrow.py +276 -0
- nexus/tests/test_exceptions.py +225 -0
- nexus/tests/test_registry.py +232 -0
- nexus/tests/test_reputation.py +328 -0
- nexus/tests/test_schemas.py +295 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
"""
|
|
4
|
+
Mistral AI Integration
|
|
5
|
+
|
|
6
|
+
Wraps Mistral's Chat API with Agent OS governance.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
from agent_os.integrations.mistral_adapter import MistralKernel
|
|
10
|
+
|
|
11
|
+
kernel = MistralKernel(policy=GovernancePolicy(
|
|
12
|
+
max_tokens=4096,
|
|
13
|
+
allowed_tools=["web_search"],
|
|
14
|
+
blocked_patterns=["password"],
|
|
15
|
+
))
|
|
16
|
+
|
|
17
|
+
governed = kernel.wrap(client)
|
|
18
|
+
response = governed.chat(
|
|
19
|
+
model="mistral-large-latest",
|
|
20
|
+
messages=[{"role": "user", "content": "Hello"}],
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
Features:
|
|
24
|
+
- Pre-execution policy checks on message content
|
|
25
|
+
- Tool call interception and validation
|
|
26
|
+
- Token limit enforcement
|
|
27
|
+
- Content filtering via blocked patterns
|
|
28
|
+
- Audit logging for all calls
|
|
29
|
+
- Health check endpoint
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
from __future__ import annotations
|
|
33
|
+
|
|
34
|
+
import logging
|
|
35
|
+
import time
|
|
36
|
+
from dataclasses import dataclass, field
|
|
37
|
+
from datetime import datetime
|
|
38
|
+
from typing import Any
|
|
39
|
+
|
|
40
|
+
from .base import BaseIntegration, ExecutionContext, GovernancePolicy
|
|
41
|
+
|
|
42
|
+
logger = logging.getLogger("agent_os.mistral")
|
|
43
|
+
|
|
44
|
+
try:
|
|
45
|
+
import mistralai # noqa: F401
|
|
46
|
+
|
|
47
|
+
_HAS_MISTRAL = True
|
|
48
|
+
except ImportError:
|
|
49
|
+
_HAS_MISTRAL = False
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _check_mistral_available() -> None:
|
|
53
|
+
"""Raise a helpful error when the ``mistralai`` package is missing."""
|
|
54
|
+
if not _HAS_MISTRAL:
|
|
55
|
+
raise ImportError(
|
|
56
|
+
"The 'mistralai' package is required for MistralKernel. "
|
|
57
|
+
"Install it with: pip install mistralai"
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass
|
|
62
|
+
class MistralContext(ExecutionContext):
|
|
63
|
+
"""Execution context for Mistral AI interactions.
|
|
64
|
+
|
|
65
|
+
Attributes:
|
|
66
|
+
model: The model used for this session.
|
|
67
|
+
chat_ids: Recorded chat completion response IDs.
|
|
68
|
+
function_calls: History of function/tool calls returned by Mistral.
|
|
69
|
+
prompt_tokens: Cumulative prompt tokens consumed.
|
|
70
|
+
completion_tokens: Cumulative completion tokens consumed.
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
model: str = ""
|
|
74
|
+
chat_ids: list[str] = field(default_factory=list)
|
|
75
|
+
function_calls: list[dict[str, Any]] = field(default_factory=list)
|
|
76
|
+
prompt_tokens: int = 0
|
|
77
|
+
completion_tokens: int = 0
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class PolicyViolationError(Exception):
|
|
81
|
+
"""Raised when a Mistral request violates governance policy."""
|
|
82
|
+
|
|
83
|
+
pass
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class MistralKernel(BaseIntegration):
|
|
87
|
+
"""Mistral AI adapter for Agent OS.
|
|
88
|
+
|
|
89
|
+
Provides governance for the Mistral Chat API including policy
|
|
90
|
+
enforcement, tool-call validation, token tracking, and audit logging.
|
|
91
|
+
|
|
92
|
+
Example:
|
|
93
|
+
>>> kernel = MistralKernel(policy=GovernancePolicy(max_tokens=8192))
|
|
94
|
+
>>> governed = kernel.wrap(MistralClient())
|
|
95
|
+
>>> response = governed.chat(
|
|
96
|
+
... model="mistral-large-latest",
|
|
97
|
+
... messages=[{"role": "user", "content": "Hello"}],
|
|
98
|
+
... )
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
def __init__(
|
|
102
|
+
self,
|
|
103
|
+
policy: GovernancePolicy | None = None,
|
|
104
|
+
) -> None:
|
|
105
|
+
"""Initialise the Mistral governance kernel.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
policy: Governance policy to enforce. Uses default when ``None``.
|
|
109
|
+
"""
|
|
110
|
+
super().__init__(policy)
|
|
111
|
+
self._wrapped_clients: dict[int, Any] = {}
|
|
112
|
+
self._start_time = time.monotonic()
|
|
113
|
+
self._last_error: str | None = None
|
|
114
|
+
|
|
115
|
+
def wrap(self, client: Any) -> GovernedMistralClient:
|
|
116
|
+
"""Wrap a Mistral client with governance.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
client: A ``MistralClient`` or ``Mistral`` client instance.
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
A ``GovernedMistralClient`` that enforces policy on all
|
|
123
|
+
``chat()`` calls.
|
|
124
|
+
"""
|
|
125
|
+
_check_mistral_available()
|
|
126
|
+
client_id = id(client)
|
|
127
|
+
ctx = MistralContext(
|
|
128
|
+
agent_id=f"mistral-{client_id}",
|
|
129
|
+
session_id=f"mis-{int(time.time())}",
|
|
130
|
+
policy=self.policy,
|
|
131
|
+
)
|
|
132
|
+
self.contexts[ctx.agent_id] = ctx
|
|
133
|
+
self._wrapped_clients[client_id] = client
|
|
134
|
+
|
|
135
|
+
return GovernedMistralClient(
|
|
136
|
+
client=client,
|
|
137
|
+
kernel=self,
|
|
138
|
+
ctx=ctx,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
def unwrap(self, governed_agent: Any) -> Any:
|
|
142
|
+
"""Retrieve the original unwrapped Mistral client.
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
governed_agent: A ``GovernedMistralClient`` or any object.
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
The original Mistral client if applicable, otherwise
|
|
149
|
+
*governed_agent* as-is.
|
|
150
|
+
"""
|
|
151
|
+
if isinstance(governed_agent, GovernedMistralClient):
|
|
152
|
+
return governed_agent._client
|
|
153
|
+
return governed_agent
|
|
154
|
+
|
|
155
|
+
def health_check(self) -> dict[str, Any]:
|
|
156
|
+
"""Return adapter health status.
|
|
157
|
+
|
|
158
|
+
Returns:
|
|
159
|
+
A dict with ``status``, ``backend``, ``last_error``, and
|
|
160
|
+
``uptime_seconds`` keys.
|
|
161
|
+
"""
|
|
162
|
+
uptime = time.monotonic() - self._start_time
|
|
163
|
+
has_clients = bool(self._wrapped_clients)
|
|
164
|
+
status = "degraded" if self._last_error else "healthy"
|
|
165
|
+
return {
|
|
166
|
+
"status": status,
|
|
167
|
+
"backend": "mistral",
|
|
168
|
+
"backend_connected": has_clients,
|
|
169
|
+
"last_error": self._last_error,
|
|
170
|
+
"uptime_seconds": round(uptime, 2),
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
class GovernedMistralClient:
|
|
175
|
+
"""Mistral client wrapped with Agent OS governance.
|
|
176
|
+
|
|
177
|
+
Intercepts ``chat()`` calls for policy enforcement while proxying
|
|
178
|
+
all other attributes to the underlying client.
|
|
179
|
+
"""
|
|
180
|
+
|
|
181
|
+
def __init__(
|
|
182
|
+
self,
|
|
183
|
+
client: Any,
|
|
184
|
+
kernel: MistralKernel,
|
|
185
|
+
ctx: MistralContext,
|
|
186
|
+
) -> None:
|
|
187
|
+
self._client = client
|
|
188
|
+
self._kernel = kernel
|
|
189
|
+
self._ctx = ctx
|
|
190
|
+
|
|
191
|
+
def chat(self, **kwargs: Any) -> Any:
|
|
192
|
+
"""Execute a governed chat completion.
|
|
193
|
+
|
|
194
|
+
Validates message content against blocked patterns, enforces
|
|
195
|
+
tool-call allowlists, checks token limits after completion,
|
|
196
|
+
and records an audit trail.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
**kwargs: Forwarded to ``client.chat()`` (includes ``model``,
|
|
200
|
+
``messages``, ``tools``, etc.).
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
The Mistral chat completion response.
|
|
204
|
+
|
|
205
|
+
Raises:
|
|
206
|
+
PolicyViolationError: If a governance policy is violated.
|
|
207
|
+
"""
|
|
208
|
+
# --- pre-execution checks ---
|
|
209
|
+
messages = kwargs.get("messages", [])
|
|
210
|
+
for msg in messages:
|
|
211
|
+
content = msg.get("content", "") if isinstance(msg, dict) else str(msg)
|
|
212
|
+
allowed, reason = self._kernel.pre_execute(self._ctx, content)
|
|
213
|
+
if not allowed:
|
|
214
|
+
raise PolicyViolationError(f"Message blocked: {reason}")
|
|
215
|
+
|
|
216
|
+
# Validate tools against policy
|
|
217
|
+
tools = kwargs.get("tools")
|
|
218
|
+
if tools:
|
|
219
|
+
self._validate_tools(tools)
|
|
220
|
+
|
|
221
|
+
# Enforce max_tokens cap from policy
|
|
222
|
+
requested_max = kwargs.get("max_tokens", 0)
|
|
223
|
+
if requested_max and requested_max > self._kernel.policy.max_tokens:
|
|
224
|
+
raise PolicyViolationError(
|
|
225
|
+
f"Requested max_tokens ({requested_max}) exceeds policy limit "
|
|
226
|
+
f"({self._kernel.policy.max_tokens})"
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
# Audit log
|
|
230
|
+
logger.info(
|
|
231
|
+
"Mistral chat | agent=%s model=%s",
|
|
232
|
+
self._ctx.agent_id,
|
|
233
|
+
kwargs.get("model", "unknown"),
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
# --- execute ---
|
|
237
|
+
try:
|
|
238
|
+
response = self._client.chat(**kwargs)
|
|
239
|
+
except Exception as exc:
|
|
240
|
+
self._kernel._last_error = str(exc)
|
|
241
|
+
raise
|
|
242
|
+
|
|
243
|
+
# --- post-execution checks ---
|
|
244
|
+
response_id = getattr(response, "id", f"chatcmpl-{int(time.time())}")
|
|
245
|
+
self._ctx.chat_ids.append(response_id)
|
|
246
|
+
|
|
247
|
+
# Track tokens
|
|
248
|
+
usage = getattr(response, "usage", None)
|
|
249
|
+
if usage:
|
|
250
|
+
self._ctx.prompt_tokens += getattr(usage, "prompt_tokens", 0)
|
|
251
|
+
self._ctx.completion_tokens += getattr(usage, "completion_tokens", 0)
|
|
252
|
+
|
|
253
|
+
total = self._ctx.prompt_tokens + self._ctx.completion_tokens
|
|
254
|
+
if total > self._kernel.policy.max_tokens:
|
|
255
|
+
raise PolicyViolationError(
|
|
256
|
+
f"Token limit exceeded: {total} > "
|
|
257
|
+
f"{self._kernel.policy.max_tokens}"
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
# Check for tool calls in response choices
|
|
261
|
+
choices = getattr(response, "choices", [])
|
|
262
|
+
for choice in choices:
|
|
263
|
+
message = getattr(choice, "message", None)
|
|
264
|
+
if message is None:
|
|
265
|
+
continue
|
|
266
|
+
tool_calls = getattr(message, "tool_calls", None)
|
|
267
|
+
if not tool_calls:
|
|
268
|
+
continue
|
|
269
|
+
for tc in tool_calls:
|
|
270
|
+
fn = getattr(tc, "function", None)
|
|
271
|
+
fn_name = getattr(fn, "name", "") if fn else ""
|
|
272
|
+
call_info = {
|
|
273
|
+
"id": getattr(tc, "id", ""),
|
|
274
|
+
"name": fn_name,
|
|
275
|
+
"arguments": getattr(fn, "arguments", "") if fn else "",
|
|
276
|
+
"timestamp": datetime.now().isoformat(),
|
|
277
|
+
}
|
|
278
|
+
self._ctx.function_calls.append(call_info)
|
|
279
|
+
self._ctx.tool_calls.append(call_info)
|
|
280
|
+
|
|
281
|
+
if len(self._ctx.tool_calls) > self._kernel.policy.max_tool_calls:
|
|
282
|
+
raise PolicyViolationError(
|
|
283
|
+
f"Tool call limit exceeded: "
|
|
284
|
+
f"{len(self._ctx.tool_calls)} > "
|
|
285
|
+
f"{self._kernel.policy.max_tool_calls}"
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
if self._kernel.policy.allowed_tools:
|
|
289
|
+
if fn_name not in self._kernel.policy.allowed_tools:
|
|
290
|
+
raise PolicyViolationError(
|
|
291
|
+
f"Tool not allowed: {fn_name}"
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
# Post-execute bookkeeping
|
|
295
|
+
self._kernel.post_execute(self._ctx, response)
|
|
296
|
+
|
|
297
|
+
return response
|
|
298
|
+
|
|
299
|
+
def get_context(self) -> MistralContext:
|
|
300
|
+
"""Return the execution context with the full audit trail.
|
|
301
|
+
|
|
302
|
+
Returns:
|
|
303
|
+
The ``MistralContext`` for this governed client.
|
|
304
|
+
"""
|
|
305
|
+
return self._ctx
|
|
306
|
+
|
|
307
|
+
def get_token_usage(self) -> dict[str, Any]:
|
|
308
|
+
"""Return cumulative token usage statistics.
|
|
309
|
+
|
|
310
|
+
Returns:
|
|
311
|
+
A dict with ``prompt_tokens``, ``completion_tokens``,
|
|
312
|
+
``total_tokens``, and ``limit``.
|
|
313
|
+
"""
|
|
314
|
+
return {
|
|
315
|
+
"prompt_tokens": self._ctx.prompt_tokens,
|
|
316
|
+
"completion_tokens": self._ctx.completion_tokens,
|
|
317
|
+
"total_tokens": self._ctx.prompt_tokens + self._ctx.completion_tokens,
|
|
318
|
+
"limit": self._kernel.policy.max_tokens,
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
def _validate_tools(self, tools: list[Any]) -> None:
|
|
322
|
+
"""Validate tool definitions against policy allowlist.
|
|
323
|
+
|
|
324
|
+
Args:
|
|
325
|
+
tools: List of tool definitions from the request.
|
|
326
|
+
|
|
327
|
+
Raises:
|
|
328
|
+
PolicyViolationError: If a tool is not in the allowed list.
|
|
329
|
+
"""
|
|
330
|
+
if not self._kernel.policy.allowed_tools:
|
|
331
|
+
return
|
|
332
|
+
for tool in tools:
|
|
333
|
+
if isinstance(tool, dict):
|
|
334
|
+
fn = tool.get("function", {})
|
|
335
|
+
name = fn.get("name", "") if isinstance(fn, dict) else ""
|
|
336
|
+
else:
|
|
337
|
+
fn = getattr(tool, "function", None)
|
|
338
|
+
name = getattr(fn, "name", "") if fn else ""
|
|
339
|
+
if name and name not in self._kernel.policy.allowed_tools:
|
|
340
|
+
raise PolicyViolationError(f"Tool not allowed: {name}")
|
|
341
|
+
|
|
342
|
+
def __getattr__(self, name: str) -> Any:
|
|
343
|
+
"""Proxy attribute access to the underlying Mistral client."""
|
|
344
|
+
return getattr(self._client, name)
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
def wrap_client(
|
|
348
|
+
client: Any,
|
|
349
|
+
policy: GovernancePolicy | None = None,
|
|
350
|
+
) -> GovernedMistralClient:
|
|
351
|
+
"""Quick wrapper for Mistral clients.
|
|
352
|
+
|
|
353
|
+
Args:
|
|
354
|
+
client: A Mistral client instance.
|
|
355
|
+
policy: Optional governance policy.
|
|
356
|
+
|
|
357
|
+
Returns:
|
|
358
|
+
A governed client.
|
|
359
|
+
|
|
360
|
+
Example:
|
|
361
|
+
>>> from agent_os.integrations.mistral_adapter import wrap_client
|
|
362
|
+
>>> governed = wrap_client(my_client)
|
|
363
|
+
>>> response = governed.chat(model="mistral-large-latest", ...)
|
|
364
|
+
"""
|
|
365
|
+
return MistralKernel(policy=policy).wrap(client)
|