Decorators & registration¶
LangStitch describes an application as a set of decorated functions and classes. Each decorator records a lightweight spec on a process-global registry at import time; nothing heavy is instantiated until a node actually needs it.
Every decorator works bare or parameterized:
from langstitch import skill
@skill
def echo(text: str) -> str:
return text
@skill(name="search", tools=["web"], tags=["retrieval"])
def web_search(query: str) -> list[str]:
...
The decorator catalog¶
| Decorator | Purpose |
|---|---|
@graph_node |
Register a node handler (state -> dict). |
@graph |
Register a graph builder (entrypoint=True for the root, parent=... for subgraphs). |
@skill |
Register a reusable capability. |
@input_guardrail / @output_guardrail |
Validate inbound requests / outbound responses. |
@business_policy |
Register an organizational rule (evaluated by priority). |
@persona |
Register an agent identity / system prompt. |
@configuration |
Bind a section of application.yaml to a dataclass. |
@langstitch_graph_server |
Turn a class into a runnable graph API server (protocol, port, name, properties). |
@tool |
Register a callable an LLM can invoke (roles, tags, input_schema). |
@worker_agent |
Register a delegatable sub-agent (role, tools, persona). |
@langstitch_mcp_server |
Mark the MCP server class + transport (protocol, properties). |
@mcp_tool |
Expose a callable as an MCP tool (name, roles, description). |
@mcp_resource |
Expose a readable MCP resource (name, uri, mime_type). |
@mcp_prompt |
Expose a reusable MCP prompt (name, description, arguments). |
Worked example¶
from langstitch import (
graph, graph_node, skill, persona,
input_guardrail, output_guardrail, business_policy,
tool, worker_agent, configuration,
langstitch_graph_server, GraphBuilder, END,
)
@persona(role="assistant", tone="helpful, concise")
def assistant() -> str:
return "You are a helpful LangStitch support assistant."
@tool(tags=["billing"], roles=["agent"])
def lookup_invoice(invoice_id: str) -> dict:
"""Fetch an invoice by id."""
...
@input_guardrail(description="Reject empty/oversized input.", action="block")
def non_empty(text: str) -> bool:
return bool(text and 0 < len(text) <= 8000)
@business_policy(priority=100, description="Deny refunds over policy limit.")
def refund_limit(context: dict) -> dict:
amount = context.get("amount", 0)
return {"decision": "deny" if amount > 1000 else "allow"}
@graph_node(description="Answer the latest message.")
def respond(state: dict) -> dict:
...
return {"response": "...", "messages": [...]}
@graph(name="main", entrypoint=True)
def main_graph() -> GraphBuilder:
g = GraphBuilder("main")
g.add_node("respond", respond)
g.set_entry_point("respond")
g.add_edge("respond", END)
return g
@langstitch_graph_server(name="my-agent", protocol="http", port=8000)
class Server:
"""Graph API server."""
Registration is import-time
A decorator runs when its module is imported, so make sure each module is
reachable from app/__init__.py. If a component is missing from
langstitch info, its module almost certainly wasn't imported.
Related¶
- Graphs & nodes โ wiring
@graphand@graph_node - Guardrails, policies & personas
- MCP โ the
@mcp_*family - API reference โ full symbol list