Skip to main content

FastICRL

PyPI version Python License: MIT Powered by agno

In-Context Reinforcement Learning for LLMs — no fine-tuning, no gradient updates.

FastICRL implements the ICRL paradigm from Reward Is Enough: LLMs Are In-Context Reinforcement Learners (Song et al., 2025). A learner LLM improves its outputs purely by reading its own history of attempts and rewards inside the context window — guided by a meta-cognitive strategist. No training, no infrastructure, just inference.


How it works

Three LLM agents collaborate in a feedback loop:

┌──────────────────────────────────────────────────┐
│                   ICRLLearner                    │
│                                                  │
│  Task ──► Learner ──► Output ──► Reward Agent    │
│             ▲                         │          │
│             │        Attempt          │          │
│             │  (task, output, score)  │          │
│             └─────────────────────────┘          │
│                          │                       │
│                  (every N episodes)              │
│                          ▼                       │
│                      Strategist                  │
│                (refines the strategy)            │
└──────────────────────────────────────────────────┘
Agent Role
Learner Generates task outputs; balances exploration vs. exploitation based on reward history
Reward Scores each output on a 0–10 scale (acts as the reward function)
Strategist Analyzes past attempts to synthesize actionable strategies for future episodes

Each agent can be backed by a different model — e.g. a cheap model for reward, a powerful one for the learner.


Installation

pip install fasticrl

Or with uv:

uv add fasticrl

Model provider extras (install whichever you use):

pip install "fasticrl[openai]"   # OpenAI
pip install "fasticrl[ollama]"   # Ollama (local models)

Requires Python ≥ 3.13.


Quick start

from fasticrl import ICRLLearner
from agno.models.openai import OpenAIChat

model = OpenAIChat(id="gpt-4o-mini")

learner = ICRLLearner(
    learner_model=model,
    reward_model=model,
    strategy_model=model,
    task_description="Write a concise, compelling product description for an e-commerce listing.",
    tasks=[
        "Wireless noise-cancelling headphones",
        "Ergonomic standing desk",
        "Portable espresso maker",
    ],
)

# Run 3 episodes, update strategy every 2 steps, show progress bar
learner.auto_learn(episodes=3, batch_size=2, cli_mode=True, strategy_update_interval=2)

# Inspect what the agent learned
print(learner.strategy)

API

ICRLLearner

ICRLLearner(
    learner_model,        # agno Model for the learner agent
    reward_model,         # agno Model for the reward agent (optional; needed for training)
    strategy_model,       # agno Model for the strategist agent (optional; needed for strategy updates)
    task_description,     # the agent's domain/identity framing (required)
    tasks,                # list of concrete task instances to cycle through
    buffer,               # optional: pre-loaded list of Attempt objects
    strategy,             # optional: pre-loaded strategy string
)

Note: task_description should carry only the agent's domain/identity framing (what kind of expert it is, what it works on). Do not include exploration or learning instructions — those are FastICRL's job, baked into its own system prompts.

Key methods

Method Description
auto_learn(episodes, batch_size, cli_mode, strategy_update_interval) Run N episodes. batch_size > 1 parallelizes tasks with a thread pool. cli_mode=True shows a progress bar. strategy_update_interval=K refreshes the strategy every K episodes.
generate_action(task) Run the learner on a single task and return its output
generate_reward(task, action) Score a learner output with the reward agent
generate_attempt_by_present_task() Single step: generate + score the current task
update_strategy() Ask the strategist to refine the strategy from the current buffer
train() / eval() Switch between training mode (default) and inference mode; mode property reports the current mode
run(task) Eval-mode inference: one LLM call applying the learned strategy, returns the answer string
eval_system_message() The frozen-policy system prompt (task_description + eval framing + strategy + experience buffer)
to_eval_agent(model=None, name=None) Build a plain agno Agent with the eval system prompt — e.g. to embed the trained expert in an agno Team
to_yaml(path) Persist the full agent state (buffer + strategy) to a YAML file
ICRLLearner.from_yaml(path, ...) Resume from a saved state (reward_model/strategy_model optional for eval-only use)

Saving and resuming

# Save
learner.to_yaml("my_agent.yaml")

# Resume later
learner = ICRLLearner.from_yaml(
    "my_agent.yaml",
    learner_model=model,
    reward_model=model,
    strategy_model=model,
)
learner.auto_learn(episodes=5)

Inference (eval mode)

Once trained, an agent can be switched to eval mode — a frozen policy that applies the learned strategy in a single LLM call per task: no reward scoring, no buffer growth, no exploration.

# Train and persist
learner.auto_learn(episodes=5)
learner.to_yaml("expert.yaml")

# Later: load for inference only — no reward/strategy models needed
expert = ICRLLearner.from_yaml("expert.yaml", learner_model=model).eval()
answer = expert.run("Compact mechanical keyboard")

To embed a trained expert as a member of an agno Team, use to_eval_agent() — it returns a plain agno Agent carrying the frozen-policy system prompt (leave model=None to let the team supply one):

expert_agent = expert.to_eval_agent(name="copywriting-expert")

Using Ollama (local models)

from agno.models.ollama import Ollama

learner = ICRLLearner(
    learner_model=Ollama(id="llama3.2"),
    reward_model=Ollama(id="llama3.2"),
    strategy_model=Ollama(id="llama3.2"),
    task_description="...",
    tasks=[...],
)

Any agno-compatible model works.


Citation

This project is based on and inspired by the following papers:

Reward Is Enough: LLMs Are In-Context Reinforcement Learners
Kefan Song, Amir Moeini, Peng Wang, Lei Gong, Rohan Chandra, Shangtong Zhang, Yanjun Qi
arXiv:2506.06303 — https://arxiv.org/abs/2506.06303

Large Language Models as Optimizers
Chengrun Yang, Xuezhi Wang, Yifeng Lu, Hanxiao Liu, Quoc V. Le, Denny Zhou, Xinyun Chen
arXiv:2309.03409 — https://arxiv.org/abs/2309.03409

Prompted Policy Search: Reinforcement Learning through Linguistic and Numerical Reasoning in LLMs
Yifan Zhou, Sachin Grover, Mohamed El Mistiri, Kamalesh Kalirathinam, Pratyush Kerhalkar, Swaroop Mishra, Neelesh Kumar, Sanket Gaurav, Oya Aran, Heni Ben Amor
NeurIPS 2025 — https://openreview.net/forum?id=95plu1Mo20


License

MIT

Metadata

Release files for fasticrl 1.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fasticrl 1.1.2
File Size Uploaded
fasticrl-1.1.2.tar.gz 9.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fasticrl 1.1.2
File Interpreter ABI Platform
fasticrl-1.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 25.4 kB

Release files / fasticrl-1.1.2.tar.gz

Download URL fasticrl-1.1.2.tar.gz
Size 9.8 kB
Tags Source
SHA-256 checksum
How to use checksums
fb4afd9717324ca500b9a49734734f9c293508e99644929161360a6829224cde
BLAKE2b-256 checksum
How to use checksums
9c4073e157ba14ff801a01bbe28852905ff4a8a351661456aeb3f17bee498c3c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 17, 2026.

Transparency log

Release files / fasticrl-1.1.2-py3-none-any.whl

Download URL fasticrl-1.1.2-py3-none-any.whl
Size 15.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f17bab965749f3fb2e16a46936aaf444f82764337d261f1a59cd599975a8b0b2
BLAKE2b-256 checksum
How to use checksums
2e374b85417be3a09c7f8554ab13b6100b8c4c2d56121937ffa2e6b0343d749e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 17, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.1.2 This release

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page