adapt-agent 0.2.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 (64) hide show
  1. adapt_agent/__init__.py +100 -0
  2. adapt_agent/__main__.py +8 -0
  3. adapt_agent/adapters/__init__.py +47 -0
  4. adapt_agent/adapters/_governed.py +496 -0
  5. adapt_agent/adapters/base.py +79 -0
  6. adapt_agent/adapters/claude_agent/__init__.py +49 -0
  7. adapt_agent/adapters/crewai/__init__.py +71 -0
  8. adapt_agent/adapters/google_adk/__init__.py +50 -0
  9. adapt_agent/adapters/langgraph/__init__.py +45 -0
  10. adapt_agent/adapters/microsoft_agent_framework/__init__.py +47 -0
  11. adapt_agent/adapters/openai_agents/__init__.py +65 -0
  12. adapt_agent/adapters/pydantic_ai/__init__.py +45 -0
  13. adapt_agent/adversarial/__init__.py +254 -0
  14. adapt_agent/cli/__init__.py +885 -0
  15. adapt_agent/cli/__main__.py +8 -0
  16. adapt_agent/core/__init__.py +13 -0
  17. adapt_agent/core/memory.py +223 -0
  18. adapt_agent/core/middleware.py +288 -0
  19. adapt_agent/core/policy.py +404 -0
  20. adapt_agent/core/trust.py +200 -0
  21. adapt_agent/core/types.py +82 -0
  22. adapt_agent/evaluation/__init__.py +209 -0
  23. adapt_agent/exceptions.py +52 -0
  24. adapt_agent/observability/__init__.py +287 -0
  25. adapt_agent/optimization/__init__.py +191 -0
  26. adapt_agent/optimization/config.py +701 -0
  27. adapt_agent/optimization/dataset.py +271 -0
  28. adapt_agent/optimization/evals.py +257 -0
  29. adapt_agent/optimization/evaluation.py +329 -0
  30. adapt_agent/optimization/extractors.py +346 -0
  31. adapt_agent/optimization/introspection/__init__.py +305 -0
  32. adapt_agent/optimization/introspection/claude_agent.py +150 -0
  33. adapt_agent/optimization/introspection/crewai.py +190 -0
  34. adapt_agent/optimization/introspection/google_adk.py +218 -0
  35. adapt_agent/optimization/introspection/langgraph.py +245 -0
  36. adapt_agent/optimization/introspection/microsoft_agent_framework.py +177 -0
  37. adapt_agent/optimization/introspection/openai_agents.py +219 -0
  38. adapt_agent/optimization/introspection/pydantic_ai.py +238 -0
  39. adapt_agent/optimization/judge.py +771 -0
  40. adapt_agent/optimization/judges.py +254 -0
  41. adapt_agent/optimization/metrics.py +424 -0
  42. adapt_agent/optimization/optimizers.py +815 -0
  43. adapt_agent/optimization/parameters.py +307 -0
  44. adapt_agent/optimization/performance.py +201 -0
  45. adapt_agent/optimization/proposers.py +464 -0
  46. adapt_agent/optimization/providers.py +783 -0
  47. adapt_agent/optimization/runners.py +244 -0
  48. adapt_agent/optimization/target.py +318 -0
  49. adapt_agent/patches/__init__.py +114 -0
  50. adapt_agent/py.typed +0 -0
  51. adapt_agent/security/__init__.py +11 -0
  52. adapt_agent/security/firewall.py +366 -0
  53. adapt_agent/security/taint_tracker.py +346 -0
  54. adapt_agent/skills/__init__.py +460 -0
  55. adapt_agent/skills/adapt-agent/SKILL.md +232 -0
  56. adapt_agent/skills/adapt-agent/references/evals.md +248 -0
  57. adapt_agent/skills/adapt-agent/references/guardrails.md +313 -0
  58. adapt_agent/skills/adapt-agent/references/optimization.md +227 -0
  59. adapt_agent-0.2.0.dist-info/METADATA +401 -0
  60. adapt_agent-0.2.0.dist-info/RECORD +64 -0
  61. adapt_agent-0.2.0.dist-info/WHEEL +5 -0
  62. adapt_agent-0.2.0.dist-info/entry_points.txt +3 -0
  63. adapt_agent-0.2.0.dist-info/licenses/LICENSE +21 -0
  64. adapt_agent-0.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,79 @@
1
+ """Base adapter interface for framework integrations."""
2
+
3
+ from abc import ABC, abstractmethod
4
+ from typing import Any
5
+
6
+ from adapt_agent.core.types import Agent, AgentState
7
+
8
+
9
+ class BaseAdapter(ABC):
10
+ """Base class for framework adapters.
11
+
12
+ Adapters provide integration with different LLM agent frameworks,
13
+ converting framework-specific APIs to ADAPT-Agent's unified interface.
14
+ """
15
+
16
+ def __init__(self, config: dict[str, Any] | None = None):
17
+ """Initialize the adapter.
18
+
19
+ Args:
20
+ config: Optional configuration dictionary
21
+ """
22
+ self.config = config or {}
23
+
24
+ @abstractmethod
25
+ def wrap_agent(self, agent: Any) -> Agent:
26
+ """Wrap a framework-specific agent with ADAPT-Agent capabilities.
27
+
28
+ Args:
29
+ agent: Framework-specific agent instance
30
+
31
+ Returns:
32
+ Wrapped agent implementing the Agent protocol
33
+ """
34
+ pass
35
+
36
+ @abstractmethod
37
+ def extract_state(self, agent: Any) -> AgentState:
38
+ """Extract the current state from a framework-specific agent.
39
+
40
+ Args:
41
+ agent: Framework-specific agent instance
42
+
43
+ Returns:
44
+ AgentState representing the current state
45
+ """
46
+ pass
47
+
48
+ @abstractmethod
49
+ def inject_middleware(self, agent: Any, middleware: Any) -> Any:
50
+ """Inject ADAPT-Agent middleware into a framework-specific agent.
51
+
52
+ Args:
53
+ agent: Framework-specific agent instance
54
+ middleware: Middleware to inject
55
+
56
+ Returns:
57
+ Modified agent with middleware
58
+ """
59
+ pass
60
+
61
+ def validate_agent(self, agent: Any) -> bool:
62
+ """Validate that an agent is compatible with this adapter.
63
+
64
+ Args:
65
+ agent: Agent to validate
66
+
67
+ Returns:
68
+ True if compatible, False otherwise
69
+ """
70
+ # Default implementation - should be overridden
71
+ return True
72
+
73
+ def get_framework_name(self) -> str:
74
+ """Get the name of the framework this adapter supports.
75
+
76
+ Returns:
77
+ Framework name
78
+ """
79
+ return self.__class__.__name__.replace("Adapter", "")
@@ -0,0 +1,49 @@
1
+ """Claude Agent SDK adapter for ADAPT-Agent.
2
+
3
+ The `Claude Agent SDK <https://github.com/anthropics/claude-agent-sdk-python>`_
4
+ exposes ``query(prompt=..., options=...)``, an async generator that yields
5
+ message objects (``AssistantMessage`` with ``TextBlock`` content, terminated by
6
+ a ``ResultMessage``).
7
+
8
+ This adapter wraps the ``query`` function (or any callable accepting a
9
+ ``prompt`` keyword) and applies ADAPT-Agent's governance pipeline. The async
10
+ stream is drained to a list of messages, so ``execute`` stays synchronous and
11
+ the firewall can scan every text block in the response. Importing this module
12
+ never imports ``claude_agent_sdk``.
13
+
14
+ Example
15
+ -------
16
+ >>> from claude_agent_sdk import query # doctest: +SKIP
17
+ >>> from adapt_agent.adapters import ClaudeAgentSDKAdapter
18
+ >>> from adapt_agent.security import Firewall
19
+ >>> adapter = ClaudeAgentSDKAdapter(firewall=Firewall())
20
+ >>> guarded = adapter.wrap_agent(query) # doctest: +SKIP
21
+ >>> guarded.execute({"messages": [{"role": "user", "content": "hi"}]}) # doctest: +SKIP
22
+ """
23
+
24
+ from typing import Any
25
+
26
+ from adapt_agent.adapters._governed import GovernedAdapter, Runner, _extract_prompt
27
+
28
+
29
+ class ClaudeAgentSDKAdapter(GovernedAdapter):
30
+ """Adapter for integrating ADAPT-Agent with the Claude Agent SDK.
31
+
32
+ Wrap the SDK's ``query`` function (or any callable accepting a ``prompt``
33
+ keyword). The async message stream is drained synchronously. See
34
+ :class:`~adapt_agent.adapters._governed.GovernedAdapter` for the full
35
+ constructor signature.
36
+ """
37
+
38
+ framework_name = "Claude Agent SDK"
39
+ run_method_names = ("query", "run")
40
+ operation = "claude_agent.query"
41
+
42
+ def _prepare_input(self, payload: dict[str, Any]) -> Any:
43
+ return _extract_prompt(payload)
44
+
45
+ def _call_runner(self, runner: Runner, payload: dict[str, Any]) -> Any:
46
+ return runner(prompt=self._prepare_input(payload))
47
+
48
+
49
+ __all__ = ["ClaudeAgentSDKAdapter"]
@@ -0,0 +1,71 @@
1
+ """CrewAI adapter for ADAPT-Agent.
2
+
3
+ `CrewAI <https://docs.crewai.com>`_ orchestrates a ``Crew`` of agents that you
4
+ run with ``crew.kickoff(inputs=...)`` (sync) or ``crew.kickoff_async(...)``. The
5
+ result is a ``CrewOutput`` whose final text is on ``.raw``.
6
+
7
+ This adapter wraps a ``Crew`` (or anything exposing a callable ``kickoff`` /
8
+ ``kickoff_async`` / ``run``) and applies ADAPT-Agent's governance pipeline. The
9
+ payload's ``context`` (its non-``messages`` keys) is forwarded to ``kickoff`` as
10
+ the ``inputs`` mapping of template variables when the runner accepts it.
11
+ Importing this module never imports ``crewai``.
12
+
13
+ Example
14
+ -------
15
+ >>> from crewai import Crew # doctest: +SKIP
16
+ >>> crew = Crew(agents=[...], tasks=[...]) # doctest: +SKIP
17
+ >>> from adapt_agent.adapters import CrewAIAdapter
18
+ >>> from adapt_agent.security import Firewall
19
+ >>> adapter = CrewAIAdapter(firewall=Firewall())
20
+ >>> guarded = adapter.wrap_agent(crew) # doctest: +SKIP
21
+ >>> guarded.execute({"messages": [{"role": "user", "content": "hi"}], "topic": "AI"}) # doctest: +SKIP
22
+ """
23
+
24
+ import inspect
25
+ from typing import Any
26
+
27
+ from adapt_agent.adapters._governed import GovernedAdapter, Runner
28
+
29
+
30
+ class CrewAIAdapter(GovernedAdapter):
31
+ """Adapter for integrating ADAPT-Agent with CrewAI crews.
32
+
33
+ Wrap a ``Crew`` (or any object exposing a callable ``kickoff`` /
34
+ ``kickoff_async`` / ``run``). See
35
+ :class:`~adapt_agent.adapters._governed.GovernedAdapter` for the full
36
+ constructor signature.
37
+ """
38
+
39
+ framework_name = "CrewAI"
40
+ run_method_names = ("kickoff", "kickoff_async", "run")
41
+ operation = "crewai.kickoff"
42
+
43
+ def _prepare_input(self, payload: dict[str, Any]) -> Any:
44
+ # CrewAI's ``inputs`` are template variables, not a chat transcript.
45
+ return {k: v for k, v in payload.items() if k != "messages"}
46
+
47
+ def _call_runner(self, runner: Runner, payload: dict[str, Any]) -> Any:
48
+ inputs = self._prepare_input(payload)
49
+ # Prefer the idiomatic ``kickoff(inputs=...)`` call when supported.
50
+ if self._accepts_kwarg(runner, "inputs"):
51
+ return runner(inputs=inputs)
52
+ return runner(inputs)
53
+
54
+ @staticmethod
55
+ def _accepts_kwarg(runner: Runner, name: str) -> bool:
56
+ try:
57
+ signature = inspect.signature(runner)
58
+ except (TypeError, ValueError):
59
+ return False
60
+ for param in signature.parameters.values():
61
+ if param.kind is inspect.Parameter.VAR_KEYWORD:
62
+ return True
63
+ if param.name == name and param.kind in (
64
+ inspect.Parameter.POSITIONAL_OR_KEYWORD,
65
+ inspect.Parameter.KEYWORD_ONLY,
66
+ ):
67
+ return True
68
+ return False
69
+
70
+
71
+ __all__ = ["CrewAIAdapter"]
@@ -0,0 +1,50 @@
1
+ """Google ADK adapter for ADAPT-Agent.
2
+
3
+ The `Google Agent Development Kit <https://google.github.io/adk-docs>`_ runs an
4
+ agent through a ``Runner``: ``runner.run_async(user_id=..., session_id=...,
5
+ new_message=...)`` (an async generator of ``Event`` objects) or the sync
6
+ ``runner.run(...)``. There is no single result object -- you iterate events and
7
+ take the one where ``event.is_final_response()`` is true.
8
+
9
+ Because an ADK run needs a session plus ``user_id`` / ``session_id`` /
10
+ ``new_message`` arguments, the idiomatic wrap target here is a **callable** you
11
+ provide that performs the run and returns (or yields) the events. The adapter
12
+ drains async/sync generators automatically and screens the text inside each
13
+ event's ``content.parts``. Importing this module never imports ``google.adk``.
14
+
15
+ Example
16
+ -------
17
+ >>> from google.adk.runners import InMemoryRunner # doctest: +SKIP
18
+ >>> from google.genai import types # doctest: +SKIP
19
+ >>> runner = InMemoryRunner(agent=my_agent) # doctest: +SKIP
20
+ >>> def run(payload): # doctest: +SKIP
21
+ ... msg = types.Content(role="user", parts=[types.Part(text=payload["prompt"])])
22
+ ... return runner.run(user_id="u", session_id="s", new_message=msg)
23
+ >>> from adapt_agent.adapters import GoogleADKAdapter
24
+ >>> from adapt_agent.security import Firewall
25
+ >>> adapter = GoogleADKAdapter(firewall=Firewall())
26
+ >>> guarded = adapter.wrap_agent(run) # doctest: +SKIP
27
+ >>> guarded.execute({"prompt": "hi"}) # doctest: +SKIP
28
+ """
29
+
30
+ from adapt_agent.adapters._governed import GovernedAdapter
31
+
32
+
33
+ class GoogleADKAdapter(GovernedAdapter):
34
+ """Adapter for integrating ADAPT-Agent with Google ADK agents.
35
+
36
+ Wrap a callable ``run(payload) -> events`` that drives an ADK ``Runner`` (the
37
+ events may be a sync generator, an async generator, or a list). The full
38
+ payload dict is passed through to your callable. See
39
+ :class:`~adapt_agent.adapters._governed.GovernedAdapter` for the full
40
+ constructor signature.
41
+ """
42
+
43
+ framework_name = "Google ADK"
44
+ # An ADK run requires session/user arguments, so binding to a bare
45
+ # ``runner.run`` would mismatch its signature; wrap a callable instead.
46
+ run_method_names = ()
47
+ operation = "google_adk.run"
48
+
49
+
50
+ __all__ = ["GoogleADKAdapter"]
@@ -0,0 +1,45 @@
1
+ """LangGraph adapter for ADAPT-Agent.
2
+
3
+ This adapter wraps a compiled LangGraph graph (or any object exposing an
4
+ ``invoke`` method) with ADAPT-Agent's security and governance primitives:
5
+ a :class:`~adapt_agent.security.Firewall`, an
6
+ :class:`~adapt_agent.adversarial.AdversarialDefense`, a
7
+ :class:`~adapt_agent.core.PolicyEnforcer`, an
8
+ :class:`~adapt_agent.observability.AgentObserver` and a
9
+ :class:`~adapt_agent.core.Middleware` pipeline.
10
+
11
+ The adapter is intentionally *structural*: it integrates with anything that
12
+ looks like a compiled LangGraph graph (a callable ``invoke(state) -> state``)
13
+ rather than importing LangGraph at module load time. The optional ``langgraph``
14
+ dependency is only needed at runtime to build the graph you pass in; importing
15
+ this module never imports ``langgraph``.
16
+
17
+ Example
18
+ -------
19
+ >>> from adapt_agent.adapters import LangGraphAdapter
20
+ >>> from adapt_agent.security import Firewall
21
+ >>> fw = Firewall(max_content_length=10_000)
22
+ >>> fw.add_blocked_pattern(r"(?i)ignore previous instructions")
23
+ >>> adapter = LangGraphAdapter(firewall=fw)
24
+ >>> guarded = adapter.wrap_agent(compiled_graph) # doctest: +SKIP
25
+ >>> guarded.execute({"messages": [{"role": "user", "content": "hi"}]}) # doctest: +SKIP
26
+ """
27
+
28
+ from adapt_agent.adapters._governed import GovernedAdapter, _extract_texts
29
+
30
+
31
+ class LangGraphAdapter(GovernedAdapter):
32
+ """Adapter for integrating ADAPT-Agent with LangGraph agents.
33
+
34
+ Wrap a **compiled** LangGraph graph -- or any object exposing a callable
35
+ ``invoke(state) -> state``. See :class:`~adapt_agent.adapters._governed.GovernedAdapter`
36
+ for the full constructor signature; every security control is optional and
37
+ keyword-only.
38
+ """
39
+
40
+ framework_name = "LangGraph"
41
+ run_method_names = ("invoke",)
42
+ operation = "langgraph.invoke"
43
+
44
+
45
+ __all__ = ["LangGraphAdapter", "_extract_texts"]
@@ -0,0 +1,47 @@
1
+ """Microsoft Agent Framework adapter for ADAPT-Agent.
2
+
3
+ `Microsoft Agent Framework <https://github.com/microsoft/agent-framework>`_ is
4
+ Microsoft's unified successor to Semantic Kernel and AutoGen. Its primary
5
+ runnable object is a ``ChatAgent`` (also exported as ``Agent``), whose
6
+ ``run(prompt)`` coroutine returns an ``AgentRunResponse`` carrying the final
7
+ text on ``.text``.
8
+
9
+ This adapter wraps a ``ChatAgent`` (or anything exposing a callable ``run`` /
10
+ ``run_sync``) and applies ADAPT-Agent's governance pipeline. ``run`` is async;
11
+ the wrapper resolves the coroutine transparently, so ``execute`` stays
12
+ synchronous. Importing this module never imports ``agent_framework``.
13
+
14
+ Example
15
+ -------
16
+ >>> from agent_framework.openai import OpenAIChatClient # doctest: +SKIP
17
+ >>> agent = OpenAIChatClient().create_agent(instructions="...") # doctest: +SKIP
18
+ >>> from adapt_agent.adapters import MicrosoftAgentFrameworkAdapter
19
+ >>> from adapt_agent.security import Firewall
20
+ >>> adapter = MicrosoftAgentFrameworkAdapter(firewall=Firewall())
21
+ >>> guarded = adapter.wrap_agent(agent) # doctest: +SKIP
22
+ >>> guarded.execute({"messages": [{"role": "user", "content": "hi"}]}) # doctest: +SKIP
23
+ """
24
+
25
+ from typing import Any
26
+
27
+ from adapt_agent.adapters._governed import GovernedAdapter, _extract_prompt
28
+
29
+
30
+ class MicrosoftAgentFrameworkAdapter(GovernedAdapter):
31
+ """Adapter for integrating ADAPT-Agent with Microsoft Agent Framework agents.
32
+
33
+ Wrap a ``ChatAgent`` (or any object exposing a callable ``run`` / ``run_sync``).
34
+ The agent is run from a prompt string derived from the payload's latest user
35
+ message. See :class:`~adapt_agent.adapters._governed.GovernedAdapter` for the
36
+ full constructor signature.
37
+ """
38
+
39
+ framework_name = "Microsoft Agent Framework"
40
+ run_method_names = ("run", "run_sync")
41
+ operation = "agent_framework.run"
42
+
43
+ def _prepare_input(self, payload: dict[str, Any]) -> Any:
44
+ return _extract_prompt(payload)
45
+
46
+
47
+ __all__ = ["MicrosoftAgentFrameworkAdapter"]
@@ -0,0 +1,65 @@
1
+ """OpenAI Agents SDK adapter for ADAPT-Agent.
2
+
3
+ The `OpenAI Agents SDK <https://openai.github.io/openai-agents-python>`_ runs an
4
+ ``Agent`` through the ``Runner`` class: ``Runner.run_sync(agent, input)`` (sync)
5
+ or ``await Runner.run(agent, input)`` (async). The result is a ``RunResult``
6
+ whose final text is on ``.final_output``.
7
+
8
+ You can wrap an OpenAI ``Agent`` directly -- the adapter lazily imports
9
+ ``agents.Runner`` at execution time and drives it for you -- or wrap any plain
10
+ callable ``run(input) -> result`` if you want full control over the run
11
+ configuration. Importing this module never imports ``agents``.
12
+
13
+ Example
14
+ -------
15
+ >>> from agents import Agent # doctest: +SKIP
16
+ >>> agent = Agent(name="Assistant", instructions="...") # doctest: +SKIP
17
+ >>> from adapt_agent.adapters import OpenAIAgentsAdapter
18
+ >>> from adapt_agent.security import Firewall
19
+ >>> adapter = OpenAIAgentsAdapter(firewall=Firewall())
20
+ >>> guarded = adapter.wrap_agent(agent) # doctest: +SKIP
21
+ >>> guarded.execute({"messages": [{"role": "user", "content": "hi"}]}) # doctest: +SKIP
22
+ """
23
+
24
+ from typing import Any, Optional
25
+
26
+ from adapt_agent.adapters._governed import GovernedAdapter, Runner, _extract_prompt
27
+ from adapt_agent.exceptions import MissingDependencyError
28
+
29
+
30
+ class OpenAIAgentsAdapter(GovernedAdapter):
31
+ """Adapter for integrating ADAPT-Agent with the OpenAI Agents SDK.
32
+
33
+ Wrap an OpenAI ``Agent`` (driven via a lazily-imported ``Runner``) or any
34
+ plain callable ``run(input) -> result``. See
35
+ :class:`~adapt_agent.adapters._governed.GovernedAdapter` for the full
36
+ constructor signature.
37
+ """
38
+
39
+ framework_name = "OpenAI Agents"
40
+ run_method_names = ("run_sync", "run")
41
+ operation = "openai_agents.run"
42
+
43
+ def _resolve_runner(self, agent: Any) -> Runner | None:
44
+ # An object exposing run_sync/run (e.g. a custom runner) or a plain
45
+ # callable is used as-is.
46
+ runner = super()._resolve_runner(agent)
47
+ if runner is not None:
48
+ return runner
49
+ # Otherwise treat ``agent`` as an OpenAI Agent and drive it through the
50
+ # SDK's Runner, imported lazily so importing this module stays cheap.
51
+ return lambda prompt: self._run_with_sdk(agent, prompt)
52
+
53
+ @staticmethod
54
+ def _run_with_sdk(agent: Any, prompt: Any) -> Any:
55
+ try:
56
+ from agents import Runner
57
+ except ImportError as exc: # pragma: no cover - exercised only without the dep
58
+ raise MissingDependencyError("openai-agents", "openai-agents") from exc
59
+ return Runner.run_sync(agent, prompt)
60
+
61
+ def _prepare_input(self, payload: dict[str, Any]) -> Any:
62
+ return _extract_prompt(payload)
63
+
64
+
65
+ __all__ = ["OpenAIAgentsAdapter"]
@@ -0,0 +1,45 @@
1
+ """Pydantic AI adapter for ADAPT-Agent.
2
+
3
+ `Pydantic AI <https://ai.pydantic.dev>`_ centres on an ``Agent`` whose
4
+ ``run_sync(prompt)`` (sync) and ``run(prompt)`` (async) methods return an
5
+ ``AgentRunResult`` carrying the final output on ``.output``.
6
+
7
+ This adapter wraps a Pydantic AI ``Agent`` (or anything exposing a callable
8
+ ``run_sync`` / ``run``) and applies ADAPT-Agent's governance pipeline. Importing
9
+ this module never imports ``pydantic_ai``.
10
+
11
+ Example
12
+ -------
13
+ >>> from pydantic_ai import Agent # doctest: +SKIP
14
+ >>> agent = Agent("openai:gpt-4o", system_prompt="...") # doctest: +SKIP
15
+ >>> from adapt_agent.adapters import PydanticAIAdapter
16
+ >>> from adapt_agent.security import Firewall
17
+ >>> adapter = PydanticAIAdapter(firewall=Firewall())
18
+ >>> guarded = adapter.wrap_agent(agent) # doctest: +SKIP
19
+ >>> guarded.execute({"messages": [{"role": "user", "content": "hi"}]}) # doctest: +SKIP
20
+ """
21
+
22
+ from typing import Any
23
+
24
+ from adapt_agent.adapters._governed import GovernedAdapter, _extract_prompt
25
+
26
+
27
+ class PydanticAIAdapter(GovernedAdapter):
28
+ """Adapter for integrating ADAPT-Agent with Pydantic AI agents.
29
+
30
+ Wrap a Pydantic AI ``Agent`` (or any object exposing a callable
31
+ ``run_sync`` / ``run``). The agent is run from a prompt string derived from
32
+ the payload's latest user message. See
33
+ :class:`~adapt_agent.adapters._governed.GovernedAdapter` for the full
34
+ constructor signature.
35
+ """
36
+
37
+ framework_name = "Pydantic AI"
38
+ run_method_names = ("run_sync", "run")
39
+ operation = "pydantic_ai.run"
40
+
41
+ def _prepare_input(self, payload: dict[str, Any]) -> Any:
42
+ return _extract_prompt(payload)
43
+
44
+
45
+ __all__ = ["PydanticAIAdapter"]