Observed since 20 Oct, 21:32 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
agentbill-py-langchain
LangChain callback handler for automatic usage tracking and billing with AgentBill
Automatic usage tracking and billing for LangChain applications.
Install via pip:
pip install agentbill-langchain
With OpenAI support:
pip install agentbill-langchain[openai]
With Anthropic support:
pip install agentbill-langchain[anthropic]
from agentbill_langchain import AgentBillCallback
from langchain_openai import ChatOpenAI
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
# 1. Initialize AgentBill callback
callback = AgentBillCallback(
api_key="agb_your_api_key_here", # Get from AgentBill dashboard
base_url="https://api.agentbill.io",
customer_id="customer-123",
debug=True
)
# 2. Create LangChain chain with callback
llm = ChatOpenAI(model="gpt-4o-mini")
prompt = PromptTemplate.from_template("Tell me a joke about {topic}")
chain = LLMChain(llm=llm, prompt=prompt)
# 3. Run - everything is auto-tracked!
result = chain.invoke(
{"topic": "programming"},
config={"callbacks": [callback]}
)
print(result["text"])
# ✅ Automatically captured:
# - Prompt text (hashed for privacy)
# - Model name (gpt-4o-mini)
# - Provider (openai)
# - Token usage (prompt + completion)
# - Latency (ms)
# - Costs (calculated automatically)
# Track revenue for profitability analysis
callback.track_revenue(
event_name="chat_completion",
revenue=0.50, # What you charged the customer
metadata={"subscription_tier": "pro"}
)
from langchain.agents import initialize_agent, load_tools
tools = load_tools(["serpapi", "llm-math"], llm=llm)
agent = initialize_agent(
tools,
llm,
agent="zero-shot-react-description",
callbacks=[callback] # Add callback here
)
# All agent steps auto-tracked!
response = agent.run("What is 25% of 300?")
from langchain.chains import SimpleSequentialChain
# All chain steps tracked automatically
overall_chain = SimpleSequentialChain(
chains=[chain1, chain2, chain3],
callbacks=[callback]
)
result = overall_chain.run(input_text)
callback = AgentBillCallback(
api_key="agb_...", # Required - get from dashboard
base_url="https://...", # Required - your AgentBill instance
customer_id="customer-123", # Optional - for multi-tenant apps
account_id="account-456", # Optional - for account-level tracking
debug=True, # Optional - enable debug logging
batch_size=10, # Optional - batch signals before sending
flush_interval=5.0 # Optional - flush interval in seconds
)
The callback hooks into LangChain's lifecycle:
All data is sent to AgentBill via the unified OTEL pipeline (otel-collector endpoint) with proper authentication.
Auto-cost calculation for:
debug=True to see logsbase_url matches your instanceEvery OTLP batch this SDK exports to /functions/v1/otel-collector carries an
X-Request-Id: <uuid4> header (auto-generated per export, reused across
transport-level retries within that export). The collector deduplicates on
(company_id, request_id), so a transient 5xx / network retry will not
double-write WAL rows, spans, or billing events.
{"requestId": "..."} at the JSON envelope root.PHASE3-R3-SDK-REQUESTID-NATIVE — tracked); the collector still dedupes
those payloads on the natural key (company_id, trace_id, span_id).See the OpenTelemetry Integration docs for the full request-id contract.
MIT
Download counts and popularity will appear here as the collector receives them.
| Package / target | Requirement | Relationship |
|---|---|---|
langchainEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | langchain>=0.1.0 | runtime |
requestsEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | requests>=2.28.0 | runtime |
langchain-openaiEnvironment{
"extras": "",
"marker": "extra == \"openai\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | langchain-openai>=0.0.1; extra == "openai" | runtime |
langchain-anthropicEnvironment{
"extras": "",
"marker": "extra == \"anthropic\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | langchain-anthropic>=0.0.1; extra == "anthropic" | runtime |
pytestEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | pytest>=7.0.0; extra == "dev" | runtime |
pytest-covEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | pytest-cov>=4.0.0; extra == "dev" | runtime |
pylintEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | pylint>=2.15.0; extra == "dev" | runtime |
blackEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | black>=22.0.0; extra == "dev" | runtime |
bdist_wheel · 25.72 KB · Python py3
sdist · 24.66 KB · Python source
Observed since 20 Oct, 21:32 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package_version:e94cfde7b38a2fa74d95e4e825a99a88cde259d117b356845865764f2a6d35d4