Skip to content

Instantly share code, notes, and snippets.

@mypy-play
Created December 6, 2025 00:34
Show Gist options
  • Select an option

  • Save mypy-play/4b0a5b6b87b8fee003975b8a47756233 to your computer and use it in GitHub Desktop.

Select an option

Save mypy-play/4b0a5b6b87b8fee003975b8a47756233 to your computer and use it in GitHub Desktop.
Shared via mypy Playground
from typing import Generic, TypeVar, ParamSpec, Protocol
# ─────────────────────────────────────────────────────────────
# Base type parameters
# ─────────────────────────────────────────────────────────────
P = ParamSpec("P") # Params for __call__ and run
O = TypeVar("O") # Raw output type
S = TypeVar("S", bound=dict) # State type
# ─────────────────────────────────────────────────────────────
# Tool output wrapper
# ─────────────────────────────────────────────────────────────
class StatefulToolOutput[O, S]:
output: O
state: S
type ToolOutput[O, S] = O | StatefulToolOutput[O, S]
# ─────────────────────────────────────────────────────────────
# Dependencies protocol
# ─────────────────────────────────────────────────────────────
class AgentDepsT[S](Protocol):
version: int
state: S
D = TypeVar("D", bound=AgentDepsT[S]) # Dependency must match the state
# ─────────────────────────────────────────────────────────────
# AgentTool with __call__ + static run()
# ─────────────────────────────────────────────────────────────
class AgentTool[D, P, O, S](Generic[D, P, O, S]):
"""
A fully typed agent tool:
D = deps object type (constrained by AgentDepsT[S])
P = parameter signature
O = raw output type
S = agent state type
"""
def __call__(self, *p: P.args, **kw: P.kwargs) -> ToolOutput[O, S]:
"""
Override in subclasses.
"""
raise NotImplementedError
@staticmethod
def run(*p: P.args, **kw: P.kwargs) -> ToolOutput[O, S]:
"""
A static alternative to calling the tool, with identical typing
to __call__.
"""
raise NotImplementedError
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment