✨ Add LangChain callback handler integration
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 0
- Forks
- 0
- Avg merge
- 6h 51m
- Merged PRs (30d)
- 104
Description
Summary
Integrate zae-limiter with LangChain via a callback handler for rate limiting LLM calls in agentic workflows.
Motivation
LangChain (~100k GitHub stars) is the most popular LLM framework. A first-party integration would:
- Showcase zae-limiter's
adjust()capability - Reach a large audience
- Demonstrate the "unknown token count" use case
Use Case
Your Server → LangChain Agent → Multiple LLM calls
│
└── Rate limit the agent's total consumption
This is for server-side agentic workflows where you control the agent and want to limit its LLM usage.
Implementation Sketch
from langchain.callbacks import BaseCallbackHandler
from zae_limiter import RateLimiter, Limit
class ZAELimiterCallback(BaseCallbackHandler):
def __init__(self, limiter: RateLimiter, entity_id: str, resource: str, limits: list[Limit]):
self.limiter = limiter
self.entity_id = entity_id
self.resource = resource
self.limits = limits
self._lease = None
self._estimated = 0
async def on_llm_start(self, serialized, prompts, **kwargs):
self._estimated = estimate_tokens(prompts)
self._lease = await self.limiter.acquire(
entity_id=self.entity_id,
resource=self.resource,
limits=self.limits,
consume={"rpm": 1, "tpm": self._estimated},
).__aenter__()
async def on_llm_end(self, response, **kwargs):
actual = response.llm_output.get("token_usage", {}).get("total_tokens", 0)
await self._lease.adjust(tpm=actual - self._estimated)
await self._lease.__aexit__(None, None, None)
self._lease = None
async def on_llm_error(self, error, **kwargs):
if self._lease:
await self._lease.__aexit__(type(error), error, None)
self._lease = None
Usage
from langchain.chat_models import ChatOpenAI
limiter = RateLimiter(name="my-app", region="us-east-1")
callback = ZAELimiterCallback(
limiter=limiter,
entity_id="agent-workflow-123",
resource="gpt-4",
limits=[
Limit.per_minute("rpm", 100),
Limit.per_minute("tpm", 10000),
],
)
llm = ChatOpenAI(callbacks=[callback])
response = await llm.ainvoke("Hello!")
Investigation Needed
- Review LangChain callback lifecycle (sync vs async)
- Handle concurrent LLM calls within single agent
- Token estimation utilities
- Error handling edge cases
- LCEL (LangChain Expression Language) compatibility
Acceptance Criteria
-
ZAELimiterCallbackimplements LangChain callback interface - Pre-call acquire with token estimate
- Post-call adjust with actual tokens
- Error handling (rollback on failure)
- Works with async LangChain calls
- Documentation with examples
- Optional dependency:
pip install zae-limiter[langchain]
Related
- #161 - LiteLLM integration
- Post-1.0.0 - Need stable API first
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing LangChain's sync and async callback lifecycle, including concurrent LLM calls and LCEL compatibility. Define the optional integration around the listed acceptance criteria, then verify pre-call acquisition, token adjustment, rollback on errors, async usage, and documentation examples.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api, backend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 32/100