Framework helpers
Signatures for framework_unit(), langgraph_node(), crewai_agent(), crewai_task(), and LangChainCapseraCallback.
Five helpers for attributing work inside an agent framework. All of them do one thing: open an attribution scope for the duration of a node, task, or chain. The provider patches still capture the call itself, so nothing is counted twice.
None of them import the framework they are named after, so they are safe to use in a codebase where that framework is absent. For worked examples per framework, see Frameworks.
framework_unit()
capsera.framework_unit(
*,
agent: str,
team: str | None = None,
task_type: str | None = None,
customer_id: str | None = None,
cost_center: str | None = None,
)
Returns a decorator for any framework node, step, or task. Keyword-only. Handles
sync and async functions, and pops its scope in a finally.
The three helpers below call this one. Use it directly for a framework that has no named helper, or when you want the parameter names to read as generic.
langgraph_node()
capsera.langgraph_node(
name: str,
*,
team: str | None = None,
task_type: str | None = None,
customer_id: str | None = None,
cost_center: str | None = None,
)
name is positional; everything else is keyword-only.
from capsera import langgraph_node
@langgraph_node("planner", team="research")
def plan(state): ...
crewai_agent()
capsera.crewai_agent(
name: str,
*,
team: str | None = None,
task_type: str | None = None,
customer_id: str | None = None,
cost_center: str | None = None,
)
The same shape, for a CrewAI agent entrypoint.
crewai_task()
capsera.crewai_task(
name: str,
*,
team: str | None = None,
customer_id: str | None = None,
cost_center: str | None = None,
)
Note the missing parameter: crewai_task() sets task_type="crewai_task" itself
and takes no task_type argument. If you need a task type of your own, use
framework_unit().
LangChainCapseraCallback
capsera.LangChainCapseraCallback(
*,
agent: str,
team: str | None = None,
task_type: str | None = "langchain",
session_id: str | None = None,
customer_id: str | None = None,
cost_center: str | None = None,
)
A callback handler for LangChain's callback protocol. Keyword-only, and the only
helper here that takes session_id.
callback = capsera.LangChainCapseraCallback(agent="rag_chain", team="search")
chain.invoke({"question": "..."}, config={"callbacks": [callback]})
It pushes its scope on on_llm_start and pops it on on_llm_end and
on_llm_error, tracking depth so an unbalanced callback sequence cannot pop past
the bottom of the stack. The three handler methods accept arbitrary arguments,
which is deliberate: LangChain's callback signatures have changed across
versions, and a signature mismatch would otherwise raise inside your chain.
Reach for the decorators when the unit of work is a function you own, and for this when the work is a chain assembled at runtime.
What these helpers do not record
They set the same attribution fields as agent()
and nothing more. There is no framework name on the event — a call made through
LangGraph is distinguishable by the agent you named and by caller_file, not by
a dedicated field.