Skip to content

model

agentic_ml.core.model

The light, production-ready model exported from a research run.

:class:AgenticModel is intentionally free of any LLM / Strands dependency. It binds to the code of a single trial (its model.py and optional helpers.py) and delegates fit/predict/save/load to that trial's Model class.

Loading an :class:AgenticModel executes the trial's code. Treat saved artifacts with the same trust as a pickle.

NotFittedError

Bases: Exception

Raised when predict or save is called before fit.

AgenticModel

AgenticModel(
    model_py: str,
    helpers_py: str,
    model_cls: type,
    inner: object | None = None,
)

Wraps a trial's Model implementation as a reusable, scikit-learn-like estimator.

An :class:AgenticModel holds no model logic itself: it stores the trial's source code (model.py / helpers.py) and the Model class loaded from it, and forwards fit/predict/save/load to an instance of that class. This is what lets a research run export a plain, LLM-free object that still runs the exact code the agent wrote and evaluated.

Attributes:

Name Type Description
is_fitted bool

Whether :meth:fit (or :meth:load) has produced a usable inner model.

Build a model wrapper. Prefer :meth:from_trial or :meth:load over this directly.

Parameters:

Name Type Description Default
model_py str

Source code of the trial's model.py, kept so :meth:save can persist it alongside the fitted state.

required
helpers_py str

Source code of the trial's optional helpers.py (empty string if the trial has none).

required
model_cls type

The Model class loaded from model_py (see :func:~agentic_ml.core.contract.load_model_class), implementing the fit/predict/save/load contract checked in :mod:agentic_ml.core.contract.

required
inner object | None

An already-fitted instance of model_cls, if any (set by :meth:load); None for a freshly built, unfitted model.

None
Source code in src/agentic_ml/core/model.py
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
def __init__(
    self,
    model_py: str,
    helpers_py: str,
    model_cls: type,
    inner: object | None = None,
) -> None:
    """Build a model wrapper. Prefer :meth:`from_trial` or :meth:`load` over this directly.

    Args:
        model_py: Source code of the trial's ``model.py``, kept so :meth:`save` can
            persist it alongside the fitted state.
        helpers_py: Source code of the trial's optional ``helpers.py`` (empty string if
            the trial has none).
        model_cls: The ``Model`` class loaded from ``model_py`` (see
            :func:`~agentic_ml.core.contract.load_model_class`), implementing the
            fit/predict/save/load contract checked in :mod:`agentic_ml.core.contract`.
        inner: An already-fitted instance of ``model_cls``, if any (set by :meth:`load`);
            ``None`` for a freshly built, unfitted model.
    """
    self._model_py = model_py
    self._helpers_py = helpers_py
    self._model_cls = model_cls
    self._inner = inner

is_fitted property

is_fitted: bool

Whether the model currently has a fitted (or loaded) inner instance.

from_trial classmethod

from_trial(trial_dir: str | Path) -> AgenticModel

Build an (unfitted) model bound to the code in trial_dir.

Reads model.py (and helpers.py if present) from trial_dir and loads the Model class from them, without fitting or restoring any state. Typically called via Researcher.export_model right after research finishes.

Parameters:

Name Type Description Default
trial_dir str | Path

Directory containing a trial's model.py (and optional helpers.py), as produced by :class:~agentic_ml.core.workspace.Workspace.

required

Returns:

Type Description
AgenticModel

A new, unfitted :class:AgenticModel bound to that trial's code.

Source code in src/agentic_ml/core/model.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
@classmethod
def from_trial(cls, trial_dir: str | Path) -> AgenticModel:
    """Build an (unfitted) model bound to the code in ``trial_dir``.

    Reads ``model.py`` (and ``helpers.py`` if present) from ``trial_dir`` and loads the
    ``Model`` class from them, without fitting or restoring any state. Typically called
    via ``Researcher.export_model`` right after research finishes.

    Args:
        trial_dir: Directory containing a trial's ``model.py`` (and optional
            ``helpers.py``), as produced by :class:`~agentic_ml.core.workspace.Workspace`.

    Returns:
        A new, unfitted :class:`AgenticModel` bound to that trial's code.
    """
    trial_dir = Path(trial_dir)
    model_py = (trial_dir / _MODEL_FILE).read_text()
    helpers_file = trial_dir / _HELPERS_FILE
    helpers_py = helpers_file.read_text() if helpers_file.exists() else ""
    model_cls = load_model_class(trial_dir)
    return cls(model_py, helpers_py, model_cls)

fit

fit(X: object, y: object) -> AgenticModel

Fit a fresh instance of the underlying trial model.

Instantiates model_cls and calls its fit(X, y), replacing any previously fitted state. Safe to call more than once; each call starts from a fresh instance.

Parameters:

Name Type Description Default
X object

Feature data in whatever shape the trial's Model.fit expects (typically a pandas.DataFrame of raw feature columns).

required
y object

Target values aligned with X.

required

Returns:

Type Description
AgenticModel

self, now fitted, so calls can be chained (AgenticModel(...).fit(X, y)).

Source code in src/agentic_ml/core/model.py
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
def fit(self, X: object, y: object) -> AgenticModel:
    """Fit a fresh instance of the underlying trial model.

    Instantiates ``model_cls`` and calls its ``fit(X, y)``, replacing any previously
    fitted state. Safe to call more than once; each call starts from a fresh instance.

    Args:
        X: Feature data in whatever shape the trial's ``Model.fit`` expects (typically a
            ``pandas.DataFrame`` of raw feature columns).
        y: Target values aligned with ``X``.

    Returns:
        ``self``, now fitted, so calls can be chained (``AgenticModel(...).fit(X, y)``).
    """
    inner = self._model_cls()
    inner.fit(X, y)
    self._inner = inner
    return self

predict

predict(X: object) -> object

Predict on new data using the fitted inner model.

Parameters:

Name Type Description Default
X object

Feature data in the same shape accepted by :meth:fit.

required

Returns:

Type Description
object

The trial's raw prediction output (typically a numpy array or pandas

object

Series).

Raises:

Type Description
NotFittedError

If called before :meth:fit or :meth:load.

Source code in src/agentic_ml/core/model.py
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
def predict(self, X: object) -> object:
    """Predict on new data using the fitted inner model.

    Args:
        X: Feature data in the same shape accepted by :meth:`fit`.

    Returns:
        The trial's raw prediction output (typically a ``numpy`` array or ``pandas``
        ``Series``).

    Raises:
        NotFittedError: If called before :meth:`fit` or :meth:`load`.
    """
    if self._inner is None:
        raise NotFittedError("call fit(...) before predict(...)")
    return self._inner.predict(X)

save

save(path: str | Path) -> None

Persist the trial code plus the fitted state to path.

Writes model.py (and helpers.py if non-empty), delegates saving the fitted state to the inner model's own save under a state/ subdirectory, and writes a small manifest.json recording the contract version. The result is self-contained: :meth:load needs only this directory to reconstruct the model.

Parameters:

Name Type Description Default
path str | Path

Directory to write to; created (with parents) if it does not exist.

required

Raises:

Type Description
NotFittedError

If called before :meth:fit.

Source code in src/agentic_ml/core/model.py
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
def save(self, path: str | Path) -> None:
    """Persist the trial code plus the fitted state to ``path``.

    Writes ``model.py`` (and ``helpers.py`` if non-empty), delegates saving the fitted
    state to the inner model's own ``save`` under a ``state/`` subdirectory, and writes a
    small ``manifest.json`` recording the contract version. The result is self-contained:
    :meth:`load` needs only this directory to reconstruct the model.

    Args:
        path: Directory to write to; created (with parents) if it does not exist.

    Raises:
        NotFittedError: If called before :meth:`fit`.
    """
    if self._inner is None:
        raise NotFittedError("call fit(...) before save(...)")
    path = Path(path)
    path.mkdir(parents=True, exist_ok=True)
    (path / _MODEL_FILE).write_text(self._model_py)
    if self._helpers_py.strip():
        (path / _HELPERS_FILE).write_text(self._helpers_py)
    state_dir = path / _STATE_DIR
    state_dir.mkdir(exist_ok=True)
    self._inner.save(str(state_dir))
    manifest = {
        "contract_version": CONTRACT_VERSION,
        "has_helpers": bool(self._helpers_py.strip()),
    }
    (path / _MANIFEST_FILE).write_text(json.dumps(manifest))

load classmethod

load(path: str | Path) -> AgenticModel

Restore a fitted model previously written by :meth:save.

Loads the Model class from the saved model.py/helpers.py, then calls its load(state_dir) to restore the fitted inner instance. This executes the trial's saved code — treat saved artifacts with the same trust as a pickle (see the module docstring).

Parameters:

Name Type Description Default
path str | Path

Directory previously written by :meth:save.

required

Returns:

Type Description
AgenticModel

A fitted :class:AgenticModel ready for :meth:predict.

Source code in src/agentic_ml/core/model.py
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
@classmethod
def load(cls, path: str | Path) -> AgenticModel:
    """Restore a fitted model previously written by :meth:`save`.

    Loads the ``Model`` class from the saved ``model.py``/``helpers.py``, then calls its
    ``load(state_dir)`` to restore the fitted inner instance. This executes the trial's
    saved code — treat saved artifacts with the same trust as a pickle (see the module
    docstring).

    Args:
        path: Directory previously written by :meth:`save`.

    Returns:
        A fitted :class:`AgenticModel` ready for :meth:`predict`.
    """
    path = Path(path)
    model_cls = load_model_class(path)
    inner = model_cls.load(str(path / _STATE_DIR))
    model_py = (path / _MODEL_FILE).read_text()
    helpers_file = path / _HELPERS_FILE
    helpers_py = helpers_file.read_text() if helpers_file.exists() else ""
    return cls(model_py, helpers_py, model_cls, inner=inner)