From 0f0e30b898e46a56731ea5778710f0d58968da6a Mon Sep 17 00:00:00 2001 From: Luis Moreno Date: Thu, 13 Nov 2025 12:17:38 -0500 Subject: [PATCH 01/15] public docs scaffolding --- docs/public/building-from-scratch.md | 0 docs/public/examples/langgraph-migration.md | 0 docs/public/examples/multi-agent.md | 0 docs/public/examples/single-agent.md | 0 docs/public/getting-started.md | 0 docs/public/index.md | 0 docs/public/langgraph-users.md | 0 docs/public/what-is-codon.md | 0 8 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/public/building-from-scratch.md create mode 100644 docs/public/examples/langgraph-migration.md create mode 100644 docs/public/examples/multi-agent.md create mode 100644 docs/public/examples/single-agent.md create mode 100644 docs/public/getting-started.md create mode 100644 docs/public/index.md create mode 100644 docs/public/langgraph-users.md create mode 100644 docs/public/what-is-codon.md diff --git a/docs/public/building-from-scratch.md b/docs/public/building-from-scratch.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/public/examples/langgraph-migration.md b/docs/public/examples/langgraph-migration.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/public/examples/multi-agent.md b/docs/public/examples/multi-agent.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/public/examples/single-agent.md b/docs/public/examples/single-agent.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/public/getting-started.md b/docs/public/getting-started.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/public/index.md b/docs/public/index.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/public/langgraph-users.md b/docs/public/langgraph-users.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/public/what-is-codon.md b/docs/public/what-is-codon.md new file mode 100644 index 0000000..e69de29 From c793efdbf744648be9cd4723e0ddd8d9cd0332c5 Mon Sep 17 00:00:00 2001 From: Luis Moreno Date: Mon, 17 Nov 2025 12:49:07 -0500 Subject: [PATCH 02/15] Structure, and first draft of what is codon, getting-started, langgraph-users, and building from scratch TODO: index and finish doc strings for the api references docs --- ...anggraph-migration.md => api-reference.md} | 0 docs/public/building-from-scratch.md | 161 ++++++++++++++++++ docs/public/examples/multi-agent.md | 0 docs/public/examples/single-agent.md | 0 docs/public/getting-started.md | 100 +++++++++++ docs/public/langgraph-users.md | 75 ++++++++ docs/public/what-is-codon.md | 54 ++++++ 7 files changed, 390 insertions(+) rename docs/public/{examples/langgraph-migration.md => api-reference.md} (100%) delete mode 100644 docs/public/examples/multi-agent.md delete mode 100644 docs/public/examples/single-agent.md diff --git a/docs/public/examples/langgraph-migration.md b/docs/public/api-reference.md similarity index 100% rename from docs/public/examples/langgraph-migration.md rename to docs/public/api-reference.md diff --git a/docs/public/building-from-scratch.md b/docs/public/building-from-scratch.md index e69de29..e763e28 100644 --- a/docs/public/building-from-scratch.md +++ b/docs/public/building-from-scratch.md @@ -0,0 +1,161 @@ +# Building from Scratch + +If you're building agents from the ground up, CodonWorkload provides a flexible foundation for creating single-agent and multi-agent workflows with token-based execution and comprehensive audit trails. + +## Single-Agent Workflow + +Here's a simple Q&A agent that processes a user question: + +```python +from codon_sdk.agents import CodonWorkload +from datetime import datetime + +# Define a workload +workload = CodonWorkload(name="QA-Agent", version="0.1.0") + +# Define node functions +def call_model(message: Dict[str, Any], *, runtime, context): + prompt = message["question"] + answer = call_openai(prompt, system="You are a helpful assistant that answers questions you are asked.") + runtime.record_event("call_model", metadata={"answer_length": len(answer)}) + runtime.emit("finalize", {"question": message["question"], "answer": answer}) + return answer + +def prompt_builder(message: Dict[str, Any], *, runtime, context): + question = message["question"] + prompt = ( + "Answer the user's question in clear, friendly prose." + f"Question: {question}" + ) + runtime.record_event("prompt_created", metadata={"length": len(prompt)}) + runtime.emit("call_model", {"question": question}) + return prompt + +def finalize(message: Dict[str, Any], *, runtime, context): + result = { + "question": message["question"], + "answer": message["answer"], + "timestamp": datetime.utcnow().isoformat() + "Z", + } + runtime.record_event("finalized", metadata={"question_hash": hash(message["question"])}) + return result + +# Add the nodes +workload.add_node(call_model, name="call_model", role="llm") +workload.add_node(finalize, name="finalize", role="postprocess") +workload.add_node(prompt_builder, name="prompt_builder", role="format_prompt") + +# Define the edges +workload.add_edge("prompt_builder", "call_model") +workload.add_edge("call_model", "finalize") + +# Execute the workload +report = workload.execute({"question": "What is the meaning of life, the universe, and everything?"}, deployment_id="local") + +# Check results +final_result = report.node_results("finalize")[-1] +print(f"Logic ID: {workload.logic_id}") +``` + +## Multi-Agent Workflow + +For more complex scenarios, you can orchestrate multiple agents that collaborate through token passing and shared state: + +```python +def build_multi_agent_workload() -> CodonWorkload: + workload = CodonWorkload(name="Research-Writer", version="0.1.0") + + def planner(message: Dict[str, Any], *, runtime, context): + topic = message["topic"] + prompt = ( + "Design a concise research plan outlining key angles and questions." + f"Topic: {topic}" + "Return a numbered list with three focus areas." + ) + plan = call_openai(prompt, system="You are a strategic project planner.") + runtime.state["plan"] = plan + runtime.emit("researcher", {"topic": topic, "plan": plan}) + return plan + + def researcher(message: Dict[str, Any], *, runtime, context): + prompt = ( + "Given this plan, provide bullet insights (max 3 per focus area)." + f"Plan: {message['plan']}" + ) + insights = call_openai(prompt, system="You are an expert analyst.") + runtime.state["insights"] = insights + runtime.emit( + "writer", + { + "topic": message["topic"], + "plan": message["plan"], + "insights": insights, + }, + ) + return insights + + def writer(message: Dict[str, Any], *, runtime, context): + prompt = ( + "Write a concise executive summary (<=120 words) in a warm, professional tone." + f"Topic: {message['topic']}" + f"Plan: {message['plan']}" + f"Insights: {message['insights']}" + ) + summary = call_openai(prompt, system="You are a skilled report writer.") + runtime.record_event("summary_created", metadata={"length": len(summary)}) + return { + "topic": message["topic"], + "plan": message["plan"], + "insights": message["insights"], + "summary": summary, + } + + workload.add_node(planner, name="planner", role="planner") + workload.add_node(researcher, name="researcher", role="analyst") + workload.add_node(writer, name="writer", role="author") + workload.add_edge("planner", "researcher") + workload.add_edge("researcher", "writer") + + return workload + +# Use the multi-agent workload +multi_agent = build_multi_agent_workload() +project = {"topic": "The impact of community gardens on urban wellbeing"} +multi_report = multi_agent.execute(project, deployment_id="demo", max_steps=20) +final_document = multi_report.node_results("writer")[-1] +``` + +## Key Concepts + +### Token-Based Execution +- Each node receives a token `message` with data from previous nodes +- Nodes can emit new tokens to downstream nodes via `runtime.emit(target_node, payload)` +- Tokens carry immutable provenance with unique IDs, lineage, and timestamps + +### Runtime Operations +The `runtime` parameter provides access to workflow operations: +- `runtime.emit(node_name, payload)` - Send tokens to other nodes +- `runtime.record_event(event_type, metadata={})` - Add custom audit entries +- `runtime.state` - Shared dictionary for coordination between nodes +- `runtime.stop()` - Halt execution early + +### Audit Ledger +Every workflow execution generates a comprehensive audit trail: +- Token enqueue/dequeue events +- Node completion events +- Custom events via `runtime.record_event()` +- Execution context (deployment_id, logic_id, run_id) + +Access the audit ledger through the execution report: +```python +for event in report.ledger: + print(f"{event.timestamp.isoformat()} | {event.event_type} | {event.source_node}") +``` + +### Logic IDs +Each workload gets a deterministic Logic ID based on: +- Agent class metadata (name, version, description) +- Node definitions and their roles +- Graph topology (edges between nodes) + +Same workload structure = same Logic ID, enabling deduplication and version tracking. \ No newline at end of file diff --git a/docs/public/examples/multi-agent.md b/docs/public/examples/multi-agent.md deleted file mode 100644 index e69de29..0000000 diff --git a/docs/public/examples/single-agent.md b/docs/public/examples/single-agent.md deleted file mode 100644 index e69de29..0000000 diff --git a/docs/public/getting-started.md b/docs/public/getting-started.md index e69de29..1d0aeaa 100644 --- a/docs/public/getting-started.md +++ b/docs/public/getting-started.md @@ -0,0 +1,100 @@ +# Getting Started + +## Prerequisites +- Python 3.8 or newer +- `pip` and a virtual environment tool such as `venv` or `pipenv` +- Access to an OTLP-compatible collector if you plan to export telemetry + +## Installation +Clone the repository and install the core SDK in editable mode: + +```bash +python -m venv .venv +source .venv/bin/activate +pip install --upgrade pip +pip install -e sdk +``` + +Instrumentation packages are published independently. To work on one locally, install it the same way: + +```bash +pip install -e instrumentation-packages/codon-instrumentation-langgraph +``` + +> **Note:** The OpenAI package is currently a stub and will be populated in a future iteration. + +## Environment Configuration +| Variable | Purpose | +| -------- | ------- | +| `ORG_NAMESPACE` | Required by `NodeSpec` and instrumentation to scope identifiers. | +| `OTEL_SERVICE_NAME` | Optional service name applied during telemetry initialization. | +| `OTEL_EXPORTER_OTLP_ENDPOINT` | Configure the OTLP collector when using the default exporter. | + +Set `ORG_NAMESPACE` before constructing `NodeSpec` objects or instrumented decorators will raise a validation error. + +You can set these environment variables directly: + +```bash +export ORG_NAMESPACE=your-org-name +export OTEL_SERVICE_NAME=your-service-name # optional +export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 # optional +``` + +Or create a `.env` file in your project root: + +```bash +# Required +ORG_NAMESPACE=your-org-name + +# Optional - only needed if using telemetry +OTEL_SERVICE_NAME=your-service-name +OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 +``` + +## Working with NodeSpec +`NodeSpec` inspects Python callables to capture the function signature, type hints, and optional model metadata. It emits a deterministic SHA-256 ID that downstream systems can rely on. + +```python +from codon_sdk.instrumentation.schemas.nodespec import NodeSpec + +@track_node("summarize", role="processor") +def summarize(text: str) -> str: + ... + +# Alternatively, construct the NodeSpec directly +nodespec = NodeSpec( + org_namespace="acme", + name="summarize", + role="processor", + callable=summarize, + model_name="gpt-4o", + model_version="2024-05-13", +) +print(nodespec.id) +``` + +`NodeSpec` requires type annotations to build JSON schemas for inputs and outputs. If annotations are missing, the generated schemas may be empty. + +## Generating Logic IDs +Logic IDs canonicalize workload definitions so repeated submissions map to the same identifier. + +```python +from codon_sdk.instrumentation.schemas.logic_id import ( + AgentClass, + LogicRequest, + generate_logic_id, +) + +logic_request = LogicRequest( + agent_class=AgentClass( + name="ReportAgent", + version="0.1.0", + description="Generates weekly status reports", + ), + nodes=[nodespec], +) +logic_id = generate_logic_id(logic_request) +print(logic_id) # Stable SHA-256 hash +``` + +The hash is deterministic because nodes and topology edges are sorted prior to serialization. This enables safe retries and caching. \ No newline at end of file diff --git a/docs/public/langgraph-users.md b/docs/public/langgraph-users.md index e69de29..2fd0bfd 100644 --- a/docs/public/langgraph-users.md +++ b/docs/public/langgraph-users.md @@ -0,0 +1,75 @@ +# For LangGraph Users + +If you're already using LangGraph, the Codon SDK provides seamless integration through the `LangGraphWorkloadAdapter`. This allows you to wrap your existing StateGraphs with minimal code changes while gaining comprehensive telemetry and observability. + +## Understanding State Graph vs Compiled Graph + +LangGraph has two distinct graph representations: +- **State Graph**: The graph you define and add nodes to during development +- **Compiled Graph**: The executable version created when you want to run the graph + +The `LangGraphWorkloadAdapter` works by wrapping your StateGraph and compiling it for you, allowing you to pass compile keyword arguments for features like checkpointers and long-term memory. + +## Using LangGraphWorkloadAdapter + +The primary way to integrate LangGraph with Codon is through the `LangGraphWorkloadAdapter.from_langgraph()` method: + +```python +from langgraph.graph import StateGraph +from langgraph.checkpoint.memory import MemorySaver +from codon.instrumentation.langgraph import LangGraphWorkloadAdapter + +# Your existing StateGraph +db_agent_graph = StateGraph(SQLAnalysisState) +db_agent_graph.add_node("query_resolver_node", self.query_resolver_node) +db_agent_graph.add_node("query_executor_node", self.query_executor_node) +# ... add more nodes and edges + +# Wrap with Codon adapter +self._graph = LangGraphWorkloadAdapter.from_langgraph( + db_agent_graph, + name="LangGraphSQLAgentDemo", + version="0.1.0", + description="A SQL agent created using the LangGraph framework", + tags=["langgraph", "demo", "sql"], + compile_kwargs={"checkpointer": MemorySaver()} +) +``` + +### Automatic Node Inference + +The adapter automatically infers nodes from your StateGraph, eliminating the need to manually instrument each node with decorators. This provides comprehensive telemetry out of the box. + +### Compile Keyword Arguments + +You can pass any LangGraph compile arguments through `compile_kwargs`: +- Checkpointers for persistence +- Memory configurations +- Custom compilation options + +## Manual Instrumentation with @track_node + +If you need more granular control over specific nodes, you can still use the `@track_node` decorator: + +```python +from codon.instrumentation.langgraph import initialize_telemetry, track_node + +initialize_telemetry(service_name="codon-langgraph-demo") + +@track_node("retrieve_docs", role="retriever") +def retrieve_docs(query: str) -> List[str]: + ... +``` + +When the decorated function executes, the LangGraph package: +- materializes a `NodeSpec` and captures its ID, signature, and schemas +- wraps execution in an OpenTelemetry span (async and sync supported) +- records inputs, outputs, and wall-clock latency via standardized span attributes + +Spans are exported with `org.namespace`, `agent.framework.name`, and the Codon span names defined in `codon_sdk.instrumentation.schemas.telemetry.spans`. + +## Best Practices + +1. **Use the adapter first**: Start with `LangGraphWorkloadAdapter.from_langgraph()` for automatic instrumentation +2. **Add manual decorators sparingly**: Only use `@track_node` when you need specific control over certain nodes +3. **Initialize telemetry early**: Call `initialize_telemetry()` before creating your workloads \ No newline at end of file diff --git a/docs/public/what-is-codon.md b/docs/public/what-is-codon.md index e69de29..3393046 100644 --- a/docs/public/what-is-codon.md +++ b/docs/public/what-is-codon.md @@ -0,0 +1,54 @@ +# What is the Codon SDK? + +Codon SDK provides common building blocks for Codon agents, including immutable node specifications, logic ID generation, and a shared telemetry vocabulary. This repository also houses framework-specific instrumentation packages that emit OpenTelemetry spans enriched with Codon metadata. + +## Key Features +- Immutable `NodeSpec` records that introspect Python callables and generate stable SHA-256 identifiers tied to organization, role, and model metadata. +- Canonical logic request hashing that deduplicates workloads by agent class, participating nodes, and topology. +- OpenTelemetry span attribute catalog for agent runs, tools, LLMs, and vector database interactions. +- Pluggable instrumentation packages (e.g., LangGraph) that decorate nodes, capture latency, and forward spans to OTLP endpoints. + +## Design Philosophy + +Codon Workload is the heart of our emerging agentic framework. The principles that guide its design: + +### Guiding Principles + +1. **Portability Over Infrastructure Lock-In** + Workloads must remain portable across environments. The same logic graph should run locally, in CI, or in production without re-authoring code. Runtime concerns (telemetry, persistence, scaling) should be injectable, not baked into agents. + +2. **Audit First** + Every agent run should be replayable. Provenancewho emitted a token, when, with which payloadneeds to be preserved. This is not just a compliance checkbox; it is foundational for trust, debugging, and postmortems. + +3. **Composable Runtime** + The framework provides a default execution engine, but its components (token queues, state store, audit sink) are intended to be swappable. Teams should be able to plug in bespoke back-ends without rewriting agent logic. + +4. **Graph Flexibility** + Agents are not restricted to DAGs. Feedback loops, streaming, and reactive behaviours are first-class. The runtime must therefore handle cycles and long-lived flows gracefully. + +5. **Low Cognitive Load for Developers** + Authoring an agent should feel familiar: define functions, register them as nodes, wire edges. The runtime handles orchestration, tokens, and logging behind the scenes. + +## What We Have Today + +### Token-Based Execution +- Each node receives a token `message`, operates on it, and can emit new tokens to downstream nodes via `runtime.emit(...)`. +- Tokens carry immutable provenance: unique ID, lineage, parent link, timestamps, and origin node. +- Shared per-run state (`runtime.state`) allows nodes to coordinate while keeping logic in regular Python functions. + +### Auditable Ledger +- Every enqueue, dequeue, node completion, custom event, and stop request is recorded as an `AuditEvent`. +- `ExecutionReport` bundles node results, the audit ledger, runtime context (`deployment_id`, `logic_id`, `run_id`), and helper methods for quick inspection. +- Developers can insert their own audit entries using `runtime.record_event(...)` to add business-specific metadata. + +### Compliance-Focused Errors and Guardrails +- `WorkloadRegistrationError` highlights graph definition issues (duplicate nodes, missing edges). +- `WorkloadRuntimeError` covers invalid routing (emitting to unregistered nodes), step limit breaches, and unexpected node failures. +- `max_steps` can cap execution cycles to prevent runaway loops. + +## Why This Matters + +- **Transparency**: By default we capture the entire "tape" of an agent run. Teams can replay what happened, not just infer from logs. +- **Flexibility**: Agent authors are not boxed into DAG-only workflows. Loops, streaming, branching, and concurrent patterns are all viable. +- **Extensibility**: The framework is not tied to a single broker or storage engine. You can start with an in-memory runtime and graduate to production-grade infrastructure without refactoring agent logic. +- **Compliance Readiness**: We treat audit as a first-class feature, not an afterthought. As persistence lands, the logs will remain provable and verifiable across environments. \ No newline at end of file From f4b58ed6525e0acb989c7262dd4edea93112d107 Mon Sep 17 00:00:00 2001 From: Luis Moreno Date: Mon, 17 Nov 2025 13:43:56 -0500 Subject: [PATCH 03/15] index.md and special char fix in what-is-codon.md --- docs/public/index.md | 16 ++++++++++++++++ docs/public/what-is-codon.md | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/docs/public/index.md b/docs/public/index.md index e69de29..16ff4bf 100644 --- a/docs/public/index.md +++ b/docs/public/index.md @@ -0,0 +1,16 @@ +# Codon SDK Documentation + +Complete guide to building observable AI agents with the Codon SDK. + +## Documentation Sections + +- **[What is the Codon SDK](what-is-codon.md)** - Design philosophy and core concepts +- **[Getting Started](getting-started.md)** - Installation and basic setup +- **[For LangGraph Users](langgraph-users.md)** - Wrap existing LangGraph workflows +- **[Building from Scratch](building-from-scratch.md)** - Create agents with CodonWorkload +- **[API Reference](api-reference.md)** - Complete API documentation + +## Quick Start + +- **LangGraph users**: Start with [For LangGraph Users](langgraph-users.md) +- **New to agent frameworks**: Begin with [Getting Started](getting-started.md) \ No newline at end of file diff --git a/docs/public/what-is-codon.md b/docs/public/what-is-codon.md index 3393046..14afa4e 100644 --- a/docs/public/what-is-codon.md +++ b/docs/public/what-is-codon.md @@ -18,7 +18,7 @@ Codon Workload is the heart of our emerging agentic framework. The principles th Workloads must remain portable across environments. The same logic graph should run locally, in CI, or in production without re-authoring code. Runtime concerns (telemetry, persistence, scaling) should be injectable, not baked into agents. 2. **Audit First** - Every agent run should be replayable. Provenancewho emitted a token, when, with which payloadneeds to be preserved. This is not just a compliance checkbox; it is foundational for trust, debugging, and postmortems. + Every agent run should be replayable. Provenance—who emitted a token, when, with which payload—needs to be preserved. This is not just a compliance checkbox; it is foundational for trust, debugging, and postmortems. 3. **Composable Runtime** The framework provides a default execution engine, but its components (token queues, state store, audit sink) are intended to be swappable. Teams should be able to plug in bespoke back-ends without rewriting agent logic. From 0d0bfcc0979ab875d753ae3f9af586e2d53d00ae Mon Sep 17 00:00:00 2001 From: Luis Moreno Date: Mon, 17 Nov 2025 17:34:05 -0500 Subject: [PATCH 04/15] Docstring for 1. CodonWorkload.__init__(), add_node(), add_edge(), execute() 2. @track_node 3. NodeSpec class 4. initialize_telemetry() 5. track_llm() / track_llm_async() 6. LangGraphWorkloadAdapter.from_langgraph() --- .../instrumentation/langgraph/__init__.py | 38 +++++++++++++++++++ sdk/src/codon_sdk/agents/codon_workload.py | 36 ++++++++++++++++++ .../schemas/nodespec/__init__.py | 33 ++++++++++++++++ 3 files changed, 107 insertions(+) diff --git a/instrumentation-packages/codon-instrumentation-langgraph/codon/instrumentation/langgraph/__init__.py b/instrumentation-packages/codon-instrumentation-langgraph/codon/instrumentation/langgraph/__init__.py index c420cf1..5dd155c 100644 --- a/instrumentation-packages/codon-instrumentation-langgraph/codon/instrumentation/langgraph/__init__.py +++ b/instrumentation-packages/codon-instrumentation-langgraph/codon/instrumentation/langgraph/__init__.py @@ -65,6 +65,18 @@ def from_langgraph( def initialize_telemetry(service_name: str = SERVICE_NAME or "") -> None: + """Initialize OpenTelemetry tracing with OTLP exporter. + + Sets up a TracerProvider with BatchSpanProcessor and OTLPSpanExporter to + export spans to an OTLP collector endpoint. + + Args: + service_name: Name for the service in telemetry data. Defaults to + OTEL_SERVICE_NAME environment variable or empty string. + + Example: + >>> initialize_telemetry(service_name="codon-langgraph-demo") + """ # Set up service name resource = Resource(attributes={"service.name": service_name}) # Set up TracerProvider & Exporter @@ -322,6 +334,32 @@ def track_node( introspection_target: Optional[Callable[..., Any]] = None, nodespec_kwargs: Optional[Mapping[str, Any]] = None, ): + """Decorator to add telemetry instrumentation to a function. + + When the decorated function executes, this decorator: + - Materializes a NodeSpec and captures its ID, signature, and schemas + - Wraps execution in an OpenTelemetry span (async and sync supported) + - Records inputs, outputs, and wall-clock latency via standardized span attributes + + Args: + node_name: Unique identifier for this node. + role: The node's role in the workflow. + model_name: Optional model identifier if this node uses an AI model. + model_version: Optional model version if this node uses an AI model. + introspection_target: Optional callable to introspect instead of decorated function. + nodespec_kwargs: Optional additional kwargs passed to NodeSpec constructor. + + Returns: + The decorated function with telemetry instrumentation added. + + Example: + >>> @track_node("retrieve_docs", role="retriever") + ... def retrieve_docs(query: str) -> List[str]: + ... return ["doc1", "doc2"] + + TODO: Document what 'role' parameter specifically represents + TODO: Clarify introspection_target use case and when to use it + """ def decorator(func): spec_callable = introspection_target or func spec_kwargs = dict(nodespec_kwargs or {}) diff --git a/sdk/src/codon_sdk/agents/codon_workload.py b/sdk/src/codon_sdk/agents/codon_workload.py index 68522df..2965a85 100644 --- a/sdk/src/codon_sdk/agents/codon_workload.py +++ b/sdk/src/codon_sdk/agents/codon_workload.py @@ -269,6 +269,14 @@ def __init__( description: Optional[str] = None, tags: Optional[Sequence[str]] = None, ) -> None: + """Initialize workload with metadata. + + Args: + name: Unique identifier for the workload type. + version: Semantic version (e.g., "1.2.0"). + description: Human-readable purpose description. + tags: Categorization tags. + """ self._node_specs: Dict[str, NodeSpec] = {} self._node_functions: Dict[str, Callable[..., Any]] = {} self._edges: Set[Tuple[str, str]] = set() @@ -327,6 +335,22 @@ def add_node( model_name: Optional[str] = None, model_version: Optional[str] = None, ) -> NodeSpec: + """Add a node (computational step) to the workload. + + Args: + function: The Python function to execute for this node. + name: Unique identifier for this node within the workload. + role: The node's role in the workflow (e.g., "processor", "validator"). + org_namespace: Organization namespace for scoping. Defaults to ORG_NAMESPACE env var. + model_name: Optional model identifier if this node uses an AI model. + model_version: Optional model version if this node uses an AI model. + + Returns: + The generated NodeSpec with a unique ID. + + Raises: + WorkloadRegistrationError: If a node with this name already exists. + """ if name in self._node_specs: raise WorkloadRegistrationError(f"Node '{name}' already registered") @@ -347,6 +371,18 @@ def add_node( return nodespec def add_edge(self, source_name: str, destination_name: str) -> None: + """Add an edge between two nodes in the workload. + + Args: + source_name: Name of the source node. + destination_name: Name of the destination node. + + Raises: + WorkloadRegistrationError: If either node name doesn't exist. + + TODO: Clarify what source_name and destination_name semantically represent + TODO: Document whether this creates directed edges and how token flow works + """ if source_name not in self._node_specs: raise WorkloadRegistrationError(f"Unknown source node '{source_name}'") if destination_name not in self._node_specs: diff --git a/sdk/src/codon_sdk/instrumentation/schemas/nodespec/__init__.py b/sdk/src/codon_sdk/instrumentation/schemas/nodespec/__init__.py index 9472649..20f5d7b 100644 --- a/sdk/src/codon_sdk/instrumentation/schemas/nodespec/__init__.py +++ b/sdk/src/codon_sdk/instrumentation/schemas/nodespec/__init__.py @@ -39,6 +39,14 @@ class NodeSpecEnv(BaseModel): class NodeSpec(BaseModel): + """Immutable specification that introspects Python callables and generates stable SHA-256 identifiers. + + NodeSpec inspects Python callables to capture the function signature, type hints, and optional + model metadata. It emits a deterministic SHA-256 ID that downstream systems can rely on. + + NodeSpec requires type annotations to build JSON schemas for inputs and outputs. If annotations + are missing, the generated schemas may be empty. + """ model_config = ConfigDict(extra="forbid", frozen=True) id: str = Field( default=None, description="The NodeSpec ID generated from the NodeSpec." @@ -81,6 +89,31 @@ def __init__( model_version: Optional[str] = None, **kwargs, ): + """Create a NodeSpec by introspecting a Python callable. + + Args: + name: The name of the node. + role: The role of the node. + callable: The Python function to introspect. + org_namespace: The namespace of the calling organization. Defaults to ORG_NAMESPACE env var. + model_name: The name of the model used in the node. + model_version: The version of the model currently used. + **kwargs: Additional fields for the NodeSpec. + + Raises: + NodeSpecValidationError: If ORG_NAMESPACE environment variable not set. + + Example: + >>> nodespec = NodeSpec( + ... org_namespace="acme", + ... name="summarize", + ... role="processor", + ... callable=summarize_function, + ... model_name="gpt-4o", + ... model_version="2024-05-13" + ... ) + >>> print(nodespec.id) + """ callable_attrs = analyze_function(callable) namespace = org_namespace or os.getenv(nodespec_env.OrgNamespace) From a24cb62ed2ca13817e9c431a6101683ccb69c034 Mon Sep 17 00:00:00 2001 From: Luis Moreno Date: Mon, 17 Nov 2025 18:29:21 -0500 Subject: [PATCH 05/15] Addressing Notes: 1. Seperating Langgraph instrumentaiton as own package. 2. Broader context on What and Why Codon SDK in what-is-codon.md 3. Move Workload and LogicID examples to building-from-scratch.md --- docs/public/building-from-scratch.md | 52 ++++++++++++++++- docs/public/getting-started.md | 52 +++-------------- docs/public/index.md | 4 +- docs/public/instrumentation/index.md | 31 ++++++++++ .../langgraph.md} | 0 docs/public/what-is-codon.md | 58 +++++++++++++++---- 6 files changed, 139 insertions(+), 58 deletions(-) create mode 100644 docs/public/instrumentation/index.md rename docs/public/{langgraph-users.md => instrumentation/langgraph.md} (100%) diff --git a/docs/public/building-from-scratch.md b/docs/public/building-from-scratch.md index e763e28..fe7d91a 100644 --- a/docs/public/building-from-scratch.md +++ b/docs/public/building-from-scratch.md @@ -2,6 +2,27 @@ If you're building agents from the ground up, CodonWorkload provides a flexible foundation for creating single-agent and multi-agent workflows with token-based execution and comprehensive audit trails. +## The CodonWorkload Class + +CodonWorkload is the core class for building agents from scratch. It provides a workflow orchestrator specifically designed for AI agents, with built-in observability and compliance features. + +**Key capabilities:** +- **Node registration**: Add Python functions as workflow steps +- **Graph definition**: Connect nodes with directed edges to define execution flow +- **Token-based execution**: Messages flow between nodes with full provenance tracking +- **Audit trails**: Automatic recording of every step, decision, and data transformation +- **Runtime operations**: Nodes can emit messages, record custom events, and share state + +## Key Concepts + +**Nodes**: Individual Python functions that perform specific tasks (e.g., "summarize", "validate", "format"). Each node receives input, processes it, and can emit output to other nodes. + +**Edges**: Directed connections between nodes that define how tokens (messages) flow through your workflow. + +**Tokens**: Immutable messages that carry data between nodes, each with unique provenance tracking. + +**Runtime**: The execution context that provides nodes access to operations like `runtime.emit()`, `runtime.record_event()`, and `runtime.state`. + ## Single-Agent Workflow Here's a simple Q&A agent that processes a user question: @@ -158,4 +179,33 @@ Each workload gets a deterministic Logic ID based on: - Node definitions and their roles - Graph topology (edges between nodes) -Same workload structure = same Logic ID, enabling deduplication and version tracking. \ No newline at end of file +Same workload structure = same Logic ID, enabling deduplication and version tracking. + +**Example: Logic ID Generation and Changes** +```python +# Based on test_codon_workload.py test patterns +workload = CodonWorkload(name="TestWorkload", version="0.1.0") + +def simple_node(message, *, runtime, context): + return f"Result: {message['input']}" + +workload.add_node(simple_node, name="test_node", role="processor") + +print(f"Initial Logic ID: {workload.logic_id}") +baseline_logic_id = workload.logic_id + +# Adding a node changes the Logic ID +def echo_node(message, *, runtime, context): + return message + +workload.add_node(echo_node, name="echo", role="responder") +workload.add_edge("test_node", "echo") + +print(f"After adding node: {workload.logic_id}") +print(f"Logic ID changed? {workload.logic_id != baseline_logic_id}") # True +``` + +This deterministic identification enables: +- **Deduplication**: Skip redundant executions of the same logic +- **Version tracking**: Compare agent iterations across deployments +- **Caching**: Store and retrieve results based on stable identifiers \ No newline at end of file diff --git a/docs/public/getting-started.md b/docs/public/getting-started.md index 1d0aeaa..6428c80 100644 --- a/docs/public/getting-started.md +++ b/docs/public/getting-started.md @@ -51,50 +51,12 @@ OTEL_SERVICE_NAME=your-service-name OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 ``` -## Working with NodeSpec -`NodeSpec` inspects Python callables to capture the function signature, type hints, and optional model metadata. It emits a deterministic SHA-256 ID that downstream systems can rely on. - -```python -from codon_sdk.instrumentation.schemas.nodespec import NodeSpec - -@track_node("summarize", role="processor") -def summarize(text: str) -> str: - ... - -# Alternatively, construct the NodeSpec directly -nodespec = NodeSpec( - org_namespace="acme", - name="summarize", - role="processor", - callable=summarize, - model_name="gpt-4o", - model_version="2024-05-13", -) -print(nodespec.id) -``` +## Next Steps -`NodeSpec` requires type annotations to build JSON schemas for inputs and outputs. If annotations are missing, the generated schemas may be empty. - -## Generating Logic IDs -Logic IDs canonicalize workload definitions so repeated submissions map to the same identifier. - -```python -from codon_sdk.instrumentation.schemas.logic_id import ( - AgentClass, - LogicRequest, - generate_logic_id, -) - -logic_request = LogicRequest( - agent_class=AgentClass( - name="ReportAgent", - version="0.1.0", - description="Generates weekly status reports", - ), - nodes=[nodespec], -) -logic_id = generate_logic_id(logic_request) -print(logic_id) # Stable SHA-256 hash -``` +Now that you have the SDK installed and configured, you can: + +- **Build from scratch**: Create custom agents with [CodonWorkload](building-from-scratch.md) +- **Use existing frameworks**: Integrate with [LangGraph](instrumentation/langgraph.md) or other supported frameworks +- **Learn the APIs**: Explore detailed documentation in the [API Reference](api-reference.md) -The hash is deterministic because nodes and topology edges are sorted prior to serialization. This enables safe retries and caching. \ No newline at end of file +For detailed information about NodeSpec and Logic ID generation, see the [API Reference](api-reference.md). \ No newline at end of file diff --git a/docs/public/index.md b/docs/public/index.md index 16ff4bf..8bdf53a 100644 --- a/docs/public/index.md +++ b/docs/public/index.md @@ -6,11 +6,11 @@ Complete guide to building observable AI agents with the Codon SDK. - **[What is the Codon SDK](what-is-codon.md)** - Design philosophy and core concepts - **[Getting Started](getting-started.md)** - Installation and basic setup -- **[For LangGraph Users](langgraph-users.md)** - Wrap existing LangGraph workflows - **[Building from Scratch](building-from-scratch.md)** - Create agents with CodonWorkload +- **[Instrumentation](instrumentation/)** - Framework-specific integrations (LangGraph, OpenAI, etc.) - **[API Reference](api-reference.md)** - Complete API documentation ## Quick Start -- **LangGraph users**: Start with [For LangGraph Users](langgraph-users.md) +- **LangGraph users**: Start with [LangGraph Integration](instrumentation/langgraph.md) - **New to agent frameworks**: Begin with [Getting Started](getting-started.md) \ No newline at end of file diff --git a/docs/public/instrumentation/index.md b/docs/public/instrumentation/index.md new file mode 100644 index 0000000..a788d04 --- /dev/null +++ b/docs/public/instrumentation/index.md @@ -0,0 +1,31 @@ +# Instrumentation + +Framework-specific instrumentation packages that emit OpenTelemetry spans enriched with Codon metadata. + +## Available Integrations + +### **[LangGraph Integration](langgraph.md)** +Seamlessly integrate your existing LangGraph StateGraphs with Codon telemetry and observability. + +- Automatic node instrumentation via `LangGraphWorkloadAdapter` +- Manual function decoration with `@track_node` +- OpenTelemetry span export with Codon metadata + +## Coming Soon + +- **OpenAI Integration** - Direct instrumentation for OpenAI API calls +- **CrewAI Integration** - Support for CrewAI agent frameworks + +## Installation + +Instrumentation packages are installed separately from the core SDK: + +```bash +# Install core SDK +pip install -e sdk + +# Install specific instrumentation packages as needed +pip install -e instrumentation-packages/codon-instrumentation-langgraph +``` + +Each integration provides telemetry and observability for its respective framework while working alongside the core Codon SDK. \ No newline at end of file diff --git a/docs/public/langgraph-users.md b/docs/public/instrumentation/langgraph.md similarity index 100% rename from docs/public/langgraph-users.md rename to docs/public/instrumentation/langgraph.md diff --git a/docs/public/what-is-codon.md b/docs/public/what-is-codon.md index 14afa4e..dce55e2 100644 --- a/docs/public/what-is-codon.md +++ b/docs/public/what-is-codon.md @@ -1,12 +1,38 @@ # What is the Codon SDK? -Codon SDK provides common building blocks for Codon agents, including immutable node specifications, logic ID generation, and a shared telemetry vocabulary. This repository also houses framework-specific instrumentation packages that emit OpenTelemetry spans enriched with Codon metadata. +## Why Codon SDK? -## Key Features -- Immutable `NodeSpec` records that introspect Python callables and generate stable SHA-256 identifiers tied to organization, role, and model metadata. -- Canonical logic request hashing that deduplicates workloads by agent class, participating nodes, and topology. -- OpenTelemetry span attribute catalog for agent runs, tools, LLMs, and vector database interactions. -- Pluggable instrumentation packages (e.g., LangGraph) that decorate nodes, capture latency, and forward spans to OTLP endpoints. +Building AI agents is one thing. Operating them reliably in production is another. Most frameworks help you create agents, but leave critical gaps when it comes to audit trails, observability, and deployment portability. How do you debug a [multi-step agent workflow](building-from-scratch.md)? How do you track costs and performance across different models and API calls? How do you ensure compliance in regulated environments? How do you deploy the same agent logic across different environments without rewriting code? + +## What It Does + +Codon SDK bridges this gap by providing production-ready infrastructure for AI agents. It wraps your existing framework code with [comprehensive observability](instrumentation/), audit trails, and deployment flexibility—without forcing you to abandon the tools you already know. + +The SDK provides common building blocks including immutable node specifications, logic ID generation, and a shared telemetry vocabulary. [Framework-specific instrumentation packages](instrumentation/) emit OpenTelemetry spans enriched with Codon metadata. + +## Core Capabilities + +**Audit-First Architecture** +- Every agent run generates a complete, replayable audit trail +- Immutable provenance tracking for every decision and data transformation +- Built for environments where you need to explain AI behavior + +**Framework-Agnostic Observability** +- Instrument existing [LangGraph](instrumentation/langgraph.md), OpenAI, and other framework code with minimal changes +- Standardized OpenTelemetry output works with any monitoring stack +- [Pluggable instrumentation packages](instrumentation/) adapt to your current tools + +**Deterministic Identity System** +- Stable SHA-256 identifiers for functions, workflows, and deployments +- Enables reliable caching, deduplication, and version tracking +- Same logic produces same identifiers across environments + +**Production-Ready Execution** +- Portable logic that runs consistently from development to production +- Flexible graph patterns supporting cycles, feedback loops, and streaming +- Separation of agent logic from deployment-specific configurations + +[Get started with the core concepts →](getting-started.md) ## Design Philosophy @@ -48,7 +74,19 @@ Codon Workload is the heart of our emerging agentic framework. The principles th ## Why This Matters -- **Transparency**: By default we capture the entire "tape" of an agent run. Teams can replay what happened, not just infer from logs. -- **Flexibility**: Agent authors are not boxed into DAG-only workflows. Loops, streaming, branching, and concurrent patterns are all viable. -- **Extensibility**: The framework is not tied to a single broker or storage engine. You can start with an in-memory runtime and graduate to production-grade infrastructure without refactoring agent logic. -- **Compliance Readiness**: We treat audit as a first-class feature, not an afterthought. As persistence lands, the logs will remain provable and verifiable across environments. \ No newline at end of file +**For Development Teams:** +- **Faster debugging**: Complete visibility into multi-step agent workflows eliminates guesswork +- **Framework flexibility**: Keep using [LangGraph](instrumentation/langgraph.md), OpenAI, or other tools you know—just add observability +- **Reliable deployments**: Same agent logic runs consistently across development, staging, and production + +**For Operations Teams:** +- **Production confidence**: Comprehensive monitoring and alerting for AI agent behavior +- **Audit compliance**: Built-in provenance tracking meets regulatory requirements +- **Infrastructure independence**: Standard OpenTelemetry output works with your existing monitoring stack + +[Explore detailed API documentation →](api-reference.md) + +**For Organizations:** +- **Risk mitigation**: Full transparency into AI decision-making processes +- **Operational excellence**: Treat AI agents with the same rigor as traditional software systems +- **Strategic flexibility**: Evolve your AI stack without being locked into specific vendors or frameworks \ No newline at end of file From 047a8a429d1e1f520fb7d78a9d109e04cca61498 Mon Sep 17 00:00:00 2001 From: Luis Moreno Date: Tue, 18 Nov 2025 10:20:16 -0500 Subject: [PATCH 06/15] adding mkdocs and script to generate docs --- docs/gen_ref_pages.py | 29 +++++++++++++++++++++++++++++ mkdocs.yml | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 docs/gen_ref_pages.py create mode 100644 mkdocs.yml diff --git a/docs/gen_ref_pages.py b/docs/gen_ref_pages.py new file mode 100644 index 0000000..317c68b --- /dev/null +++ b/docs/gen_ref_pages.py @@ -0,0 +1,29 @@ +"""Generate API reference pages.""" +import mkdocs_gen_files + +# Generate content for api-reference.md +with mkdocs_gen_files.open("api-reference.md", "w") as f: + f.write("""# API Reference + +## Core SDK (`codon_sdk`) + +### Agents + +::: codon_sdk.agents.CodonWorkload + +::: codon_sdk.agents.ExecutionReport + +### Instrumentation Schemas + +::: codon_sdk.instrumentation.schemas.nodespec.NodeSpec + +::: codon_sdk.instrumentation.schemas.logic_id.LogicRequest + +## Instrumentation Packages + +### LangGraph Integration (`codon-instrumentation-langgraph`) + +::: codon.instrumentation.langgraph.track_node + +::: codon.instrumentation.langgraph.initialize_telemetry +""") \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..2a9c8d0 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,35 @@ +site_name: Codon SDK Documentation +site_description: Observable AI agents with the Codon SDK + +theme: + name: material + features: + - navigation.sections + - toc.integrate + - search.suggest + - content.code.copy + +plugins: + - search + - gen-files: + scripts: + - docs/gen_ref_pages.py + - mkdocstrings: + handlers: + python: + options: + docstring_style: google + show_root_heading: true + show_root_full_path: false + show_signature_annotations: true + +docs_dir: docs/public +nav: + - Home: index.md + - What is Codon: what-is-codon.md + - Getting Started: getting-started.md + - Building from Scratch: building-from-scratch.md + - Instrumentation: + - Overview: instrumentation/index.md + - LangGraph: instrumentation/langgraph.md + - API Reference: api-reference.md \ No newline at end of file From c4b27498fe0b07bf34cdbd31590652673bf3f0d4 Mon Sep 17 00:00:00 2001 From: Luis Moreno Date: Tue, 18 Nov 2025 11:44:25 -0500 Subject: [PATCH 07/15] pyproject.docs.toml --- pyproject.docs.toml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 pyproject.docs.toml diff --git a/pyproject.docs.toml b/pyproject.docs.toml new file mode 100644 index 0000000..fd09cbf --- /dev/null +++ b/pyproject.docs.toml @@ -0,0 +1,17 @@ +[build-system] +requires = ["setuptools>=61.0"] +build-backend = "setuptools.build_meta" + +[project] +name = "codon-sdk-docs" +version = "0.1.0" +description = "Documentation tooling for Codon SDK" +requires-python = ">=3.8" + +[project.optional-dependencies] +docs = [ + "mkdocs", + "mkdocs-material", + "mkdocstrings[python]", + "mkdocs-gen-files", +] \ No newline at end of file From b1191bb3fe95e768939a5058a16c753aa727de62 Mon Sep 17 00:00:00 2001 From: Luis Moreno Date: Wed, 19 Nov 2025 10:09:38 -0500 Subject: [PATCH 08/15] delete docs toml. just use pip isntall in workflow --- .github/workflows/docs.yml | 20 ++++++++++++++++++++ pyproject.docs.toml | 17 ----------------- 2 files changed, 20 insertions(+), 17 deletions(-) create mode 100644 .github/workflows/docs.yml delete mode 100644 pyproject.docs.toml diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..ef7632a --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,20 @@ +name: Build and Deploy Docs +on: + push: + branches: [ docs-build ] +jobs: + deploy: + runs-on: ubuntu-latest + permissions: + pages: write + id-token: write + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 + with: + python-version: '3.x' + - run: pip install mkdocs mkdocs-material 'mkdocstrings[python]' mkdocs-gen-files + - run: mkdocs build + - uses: actions/deploy-pages@v2 + with: + path: ./site \ No newline at end of file diff --git a/pyproject.docs.toml b/pyproject.docs.toml deleted file mode 100644 index fd09cbf..0000000 --- a/pyproject.docs.toml +++ /dev/null @@ -1,17 +0,0 @@ -[build-system] -requires = ["setuptools>=61.0"] -build-backend = "setuptools.build_meta" - -[project] -name = "codon-sdk-docs" -version = "0.1.0" -description = "Documentation tooling for Codon SDK" -requires-python = ">=3.8" - -[project.optional-dependencies] -docs = [ - "mkdocs", - "mkdocs-material", - "mkdocstrings[python]", - "mkdocs-gen-files", -] \ No newline at end of file From c83630fd4cf9f0713cfd55ee18042a11f1a9eb79 Mon Sep 17 00:00:00 2001 From: Luis Moreno Date: Fri, 21 Nov 2025 09:50:42 -0500 Subject: [PATCH 09/15] Revisions based on M.A. logical architecture presentation --- docs/gen_ref_pages.py | 4 ++-- docs/public/building-from-scratch.md | 4 ++-- docs/public/instrumentation/index.md | 2 +- docs/public/instrumentation/langgraph.md | 27 +++--------------------- docs/public/what-is-codon.md | 12 +++++++++-- 5 files changed, 18 insertions(+), 31 deletions(-) diff --git a/docs/gen_ref_pages.py b/docs/gen_ref_pages.py index 317c68b..7fbc124 100644 --- a/docs/gen_ref_pages.py +++ b/docs/gen_ref_pages.py @@ -23,7 +23,7 @@ ### LangGraph Integration (`codon-instrumentation-langgraph`) -::: codon.instrumentation.langgraph.track_node - ::: codon.instrumentation.langgraph.initialize_telemetry + +::: codon.instrumentation.langgraph.LangGraphWorkloadAdapter """) \ No newline at end of file diff --git a/docs/public/building-from-scratch.md b/docs/public/building-from-scratch.md index fe7d91a..fe195a8 100644 --- a/docs/public/building-from-scratch.md +++ b/docs/public/building-from-scratch.md @@ -4,7 +4,7 @@ If you're building agents from the ground up, CodonWorkload provides a flexible ## The CodonWorkload Class -CodonWorkload is the core class for building agents from scratch. It provides a workflow orchestrator specifically designed for AI agents, with built-in observability and compliance features. +CodonWorkload is the foundation for building observable AI agents. Whether you build from scratch or use frameworks like LangGraph, it gives your agents the ability to track their own performance, costs, and behavior over time. **Key capabilities:** - **Node registration**: Add Python functions as workflow steps @@ -19,7 +19,7 @@ CodonWorkload is the core class for building agents from scratch. It provides a **Edges**: Directed connections between nodes that define how tokens (messages) flow through your workflow. -**Tokens**: Immutable messages that carry data between nodes, each with unique provenance tracking. +**Tokens**: Immutable messages that carry data between nodes, each with unique provenance tracking. This creates an immutable tape of your agent's actions during invocation that can be used for compliance monitoring, audit, evaluation, debugging, and experimentation. **Runtime**: The execution context that provides nodes access to operations like `runtime.emit()`, `runtime.record_event()`, and `runtime.state`. diff --git a/docs/public/instrumentation/index.md b/docs/public/instrumentation/index.md index a788d04..9501cad 100644 --- a/docs/public/instrumentation/index.md +++ b/docs/public/instrumentation/index.md @@ -8,8 +8,8 @@ Framework-specific instrumentation packages that emit OpenTelemetry spans enrich Seamlessly integrate your existing LangGraph StateGraphs with Codon telemetry and observability. - Automatic node instrumentation via `LangGraphWorkloadAdapter` -- Manual function decoration with `@track_node` - OpenTelemetry span export with Codon metadata +- Just a few lines of code integration ## Coming Soon diff --git a/docs/public/instrumentation/langgraph.md b/docs/public/instrumentation/langgraph.md index 2fd0bfd..1ffd8ab 100644 --- a/docs/public/instrumentation/langgraph.md +++ b/docs/public/instrumentation/langgraph.md @@ -47,29 +47,8 @@ You can pass any LangGraph compile arguments through `compile_kwargs`: - Memory configurations - Custom compilation options -## Manual Instrumentation with @track_node - -If you need more granular control over specific nodes, you can still use the `@track_node` decorator: - -```python -from codon.instrumentation.langgraph import initialize_telemetry, track_node - -initialize_telemetry(service_name="codon-langgraph-demo") - -@track_node("retrieve_docs", role="retriever") -def retrieve_docs(query: str) -> List[str]: - ... -``` - -When the decorated function executes, the LangGraph package: -- materializes a `NodeSpec` and captures its ID, signature, and schemas -- wraps execution in an OpenTelemetry span (async and sync supported) -- records inputs, outputs, and wall-clock latency via standardized span attributes - -Spans are exported with `org.namespace`, `agent.framework.name`, and the Codon span names defined in `codon_sdk.instrumentation.schemas.telemetry.spans`. - ## Best Practices -1. **Use the adapter first**: Start with `LangGraphWorkloadAdapter.from_langgraph()` for automatic instrumentation -2. **Add manual decorators sparingly**: Only use `@track_node` when you need specific control over certain nodes -3. **Initialize telemetry early**: Call `initialize_telemetry()` before creating your workloads \ No newline at end of file +1. **Use the adapter**: `LangGraphWorkloadAdapter.from_langgraph()` provides comprehensive instrumentation with just a few lines of code +2. **Initialize telemetry early**: Call `initialize_telemetry()` before creating your workloads +3. **Leverage compile_kwargs**: Pass checkpointers and memory configurations through the adapter \ No newline at end of file diff --git a/docs/public/what-is-codon.md b/docs/public/what-is-codon.md index dce55e2..fb4bf51 100644 --- a/docs/public/what-is-codon.md +++ b/docs/public/what-is-codon.md @@ -2,14 +2,22 @@ ## Why Codon SDK? -Building AI agents is one thing. Operating them reliably in production is another. Most frameworks help you create agents, but leave critical gaps when it comes to audit trails, observability, and deployment portability. How do you debug a [multi-step agent workflow](building-from-scratch.md)? How do you track costs and performance across different models and API calls? How do you ensure compliance in regulated environments? How do you deploy the same agent logic across different environments without rewriting code? +There is currently no way to identify AI agents that persists between invocations or across deployment environments. Every time you deploy an AI agent, it gets a new identity. There's no way to track that your 'customer-support-bot-v2' in staging is the same logic as production, making cost analysis, performance tracking, and debugging nearly impossible. + +This gap means AI agent teams struggle to measure their runtime invocations, track usage metrics at the node-level, perform lineage reconstruction, enable cost attribution, and conduct debugging & reliability analytics across environments. ## What It Does -Codon SDK bridges this gap by providing production-ready infrastructure for AI agents. It wraps your existing framework code with [comprehensive observability](instrumentation/), audit trails, and deployment flexibility—without forcing you to abandon the tools you already know. +That's why Codon assigns Universal IDs to AI agents, intelligently encoding their logic through Node IDs and Logic IDs that persist across deployments. The SDK wraps your existing framework code with [comprehensive observability](instrumentation/), creating an immutable tape of agent actions that can be used for compliance monitoring, debugging, and cost optimization. The SDK provides common building blocks including immutable node specifications, logic ID generation, and a shared telemetry vocabulary. [Framework-specific instrumentation packages](instrumentation/) emit OpenTelemetry spans enriched with Codon metadata. +## How Codon Works: Two-Layer Architecture + +**Layer 1: The Core SDK** - Generates stable Node IDs and Logic IDs from agent graphs, plus provides the Workload interface that establishes the contract all concrete implementations must follow to communicate with the data collection system. + +**Layer 2: The Instrumentation Libraries** - Framework-specific packages that leverage the Core SDK to "wrap" third-party frameworks with telemetry sensors. Our goal is to "meet developers where they are" by making it simple to bring your existing framework and still get the visibility and insights that Codon can offer. + ## Core Capabilities **Audit-First Architecture** From 4abf7bd463aae5059df175b8baa3c1397408dfa2 Mon Sep 17 00:00:00 2001 From: Luis Moreno Date: Fri, 21 Nov 2025 09:58:38 -0500 Subject: [PATCH 10/15] Adding note about executed nodes vs graph topology in execution summary --- docs/public/building-from-scratch.md | 2 ++ docs/public/instrumentation/langgraph.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/docs/public/building-from-scratch.md b/docs/public/building-from-scratch.md index fe195a8..20e2757 100644 --- a/docs/public/building-from-scratch.md +++ b/docs/public/building-from-scratch.md @@ -167,6 +167,8 @@ Every workflow execution generates a comprehensive audit trail: - Custom events via `runtime.record_event()` - Execution context (deployment_id, logic_id, run_id) +**Note:** Only fired nodes are represented in a workload run, so the complete workload definition may not be present in the workload run summary. Your audit trail shows actual execution paths, not all possible paths defined in your workflow. + Access the audit ledger through the execution report: ```python for event in report.ledger: diff --git a/docs/public/instrumentation/langgraph.md b/docs/public/instrumentation/langgraph.md index 1ffd8ab..387d90f 100644 --- a/docs/public/instrumentation/langgraph.md +++ b/docs/public/instrumentation/langgraph.md @@ -40,6 +40,8 @@ self._graph = LangGraphWorkloadAdapter.from_langgraph( The adapter automatically infers nodes from your StateGraph, eliminating the need to manually instrument each node with decorators. This provides comprehensive telemetry out of the box. +**Note:** Only fired nodes are represented in a workload run, so the complete workload definition may not be present in the workload run summary. This is particularly relevant for LangGraph workflows with conditional edges and branching logic—your execution reports will show actual paths taken, not all possible paths. + ### Compile Keyword Arguments You can pass any LangGraph compile arguments through `compile_kwargs`: From be2a77e9431a4591c37862e39d5947f47690f3f8 Mon Sep 17 00:00:00 2001 From: Luis Moreno Date: Fri, 21 Nov 2025 10:18:56 -0500 Subject: [PATCH 11/15] Reference api docs from 'building from scratch' --- docs/public/building-from-scratch.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/public/building-from-scratch.md b/docs/public/building-from-scratch.md index 20e2757..2987406 100644 --- a/docs/public/building-from-scratch.md +++ b/docs/public/building-from-scratch.md @@ -1,6 +1,6 @@ # Building from Scratch -If you're building agents from the ground up, CodonWorkload provides a flexible foundation for creating single-agent and multi-agent workflows with token-based execution and comprehensive audit trails. +If you're building agents from the ground up, [CodonWorkload](api-reference.md#codon_sdkagentscodonworkload) provides a flexible foundation for creating single-agent and multi-agent workflows with token-based execution and comprehensive audit trails. ## The CodonWorkload Class @@ -13,6 +13,8 @@ CodonWorkload is the foundation for building observable AI agents. Whether you b - **Audit trails**: Automatic recording of every step, decision, and data transformation - **Runtime operations**: Nodes can emit messages, record custom events, and share state +For complete method signatures and parameters, see the [API Reference](api-reference.md). + ## Key Concepts **Nodes**: Individual Python functions that perform specific tasks (e.g., "summarize", "validate", "format"). Each node receives input, processes it, and can emit output to other nodes. From 50aba228e4d219cedc3b973b646b05d67f14774d Mon Sep 17 00:00:00 2001 From: Luis Moreno Date: Fri, 21 Nov 2025 11:25:28 -0500 Subject: [PATCH 12/15] Revise quickstart in index.md --- docs/public/index.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/public/index.md b/docs/public/index.md index 8bdf53a..12b4a9c 100644 --- a/docs/public/index.md +++ b/docs/public/index.md @@ -12,5 +12,6 @@ Complete guide to building observable AI agents with the Codon SDK. ## Quick Start -- **LangGraph users**: Start with [LangGraph Integration](instrumentation/langgraph.md) -- **New to agent frameworks**: Begin with [Getting Started](getting-started.md) \ No newline at end of file +1. **[Getting Started](getting-started.md)** - Installation and environment setup +2. **New to agent frameworks**: Create agents with [Building from Scratch](building-from-scratch.md) +3. **LangGraph users**: Integrate existing code with [LangGraph Integration](instrumentation/langgraph.md) \ No newline at end of file From e34c65285222e1fb0c8898005782cef2a9235516 Mon Sep 17 00:00:00 2001 From: Luis Moreno Date: Fri, 21 Nov 2025 17:13:36 -0500 Subject: [PATCH 13/15] install packaged in docs build. fix reference to links --- .github/workflows/docs.yml | 3 +++ docs/public/index.md | 2 +- docs/public/what-is-codon.md | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index ef7632a..c32614a 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -14,6 +14,9 @@ jobs: with: python-version: '3.x' - run: pip install mkdocs mkdocs-material 'mkdocstrings[python]' mkdocs-gen-files + # Install your packages so mkdocstrings can import them + - run: pip install -e sdk + - run: pip install -e instrumentation-packages/codon-instrumentation-langgraph - run: mkdocs build - uses: actions/deploy-pages@v2 with: diff --git a/docs/public/index.md b/docs/public/index.md index 12b4a9c..d495b90 100644 --- a/docs/public/index.md +++ b/docs/public/index.md @@ -7,7 +7,7 @@ Complete guide to building observable AI agents with the Codon SDK. - **[What is the Codon SDK](what-is-codon.md)** - Design philosophy and core concepts - **[Getting Started](getting-started.md)** - Installation and basic setup - **[Building from Scratch](building-from-scratch.md)** - Create agents with CodonWorkload -- **[Instrumentation](instrumentation/)** - Framework-specific integrations (LangGraph, OpenAI, etc.) +- **[Instrumentation](instrumentation/index.md)** - Framework-specific integrations (LangGraph, OpenAI, etc.) - **[API Reference](api-reference.md)** - Complete API documentation ## Quick Start diff --git a/docs/public/what-is-codon.md b/docs/public/what-is-codon.md index fb4bf51..222fea2 100644 --- a/docs/public/what-is-codon.md +++ b/docs/public/what-is-codon.md @@ -8,9 +8,9 @@ This gap means AI agent teams struggle to measure their runtime invocations, tra ## What It Does -That's why Codon assigns Universal IDs to AI agents, intelligently encoding their logic through Node IDs and Logic IDs that persist across deployments. The SDK wraps your existing framework code with [comprehensive observability](instrumentation/), creating an immutable tape of agent actions that can be used for compliance monitoring, debugging, and cost optimization. +That's why Codon assigns Universal IDs to AI agents, intelligently encoding their logic through Node IDs and Logic IDs that persist across deployments. The SDK wraps your existing framework code with [comprehensive observability](instrumentation/index.md), creating an immutable tape of agent actions that can be used for compliance monitoring, debugging, and cost optimization. -The SDK provides common building blocks including immutable node specifications, logic ID generation, and a shared telemetry vocabulary. [Framework-specific instrumentation packages](instrumentation/) emit OpenTelemetry spans enriched with Codon metadata. +The SDK provides common building blocks including immutable node specifications, logic ID generation, and a shared telemetry vocabulary. [Framework-specific instrumentation packages](instrumentation/index.md) emit OpenTelemetry spans enriched with Codon metadata. ## How Codon Works: Two-Layer Architecture From c11b7833781fc85e9cc963fb8486b685f68d5425 Mon Sep 17 00:00:00 2001 From: Luis Moreno Date: Sun, 23 Nov 2025 20:31:58 -0500 Subject: [PATCH 14/15] Using artifact upload because we are using build from action not static pages. Also corrects links in docs --- .github/workflows/docs.yml | 10 +++++++--- docs/public/building-from-scratch.md | 2 +- docs/public/what-is-codon.md | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index c32614a..054ffc1 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -8,16 +8,20 @@ jobs: permissions: pages: write id-token: write + contents: read steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v4 with: python-version: '3.x' - run: pip install mkdocs mkdocs-material 'mkdocstrings[python]' mkdocs-gen-files - # Install your packages so mkdocstrings can import them + # Install packages so mkdocstrings can import them - run: pip install -e sdk - run: pip install -e instrumentation-packages/codon-instrumentation-langgraph - run: mkdocs build - - uses: actions/deploy-pages@v2 + # Upload artifact for Pages + - uses: actions/upload-pages-artifact@v3 with: - path: ./site \ No newline at end of file + path: ./site + # Deploy from artifact + - uses: actions/deploy-pages@v4 \ No newline at end of file diff --git a/docs/public/building-from-scratch.md b/docs/public/building-from-scratch.md index 2987406..2351ba7 100644 --- a/docs/public/building-from-scratch.md +++ b/docs/public/building-from-scratch.md @@ -1,6 +1,6 @@ # Building from Scratch -If you're building agents from the ground up, [CodonWorkload](api-reference.md#codon_sdkagentscodonworkload) provides a flexible foundation for creating single-agent and multi-agent workflows with token-based execution and comprehensive audit trails. +If you're building agents from the ground up, [CodonWorkload](api-reference.md#codon_sdk.agents.CodonWorkload) provides a flexible foundation for creating single-agent and multi-agent workflows with token-based execution and comprehensive audit trails. ## The CodonWorkload Class diff --git a/docs/public/what-is-codon.md b/docs/public/what-is-codon.md index 222fea2..88a81c6 100644 --- a/docs/public/what-is-codon.md +++ b/docs/public/what-is-codon.md @@ -28,7 +28,7 @@ The SDK provides common building blocks including immutable node specifications, **Framework-Agnostic Observability** - Instrument existing [LangGraph](instrumentation/langgraph.md), OpenAI, and other framework code with minimal changes - Standardized OpenTelemetry output works with any monitoring stack -- [Pluggable instrumentation packages](instrumentation/) adapt to your current tools +- [Pluggable instrumentation packages](instrumentation/index.md) adapt to your current tools **Deterministic Identity System** - Stable SHA-256 identifiers for functions, workflows, and deployments From 937d06293e4f3241c1dc2f3909c80f58e08028ec Mon Sep 17 00:00:00 2001 From: Luis Moreno Date: Mon, 24 Nov 2025 16:06:25 -0500 Subject: [PATCH 15/15] Need to remove the explicit depedency on the sdk built from main since that overrides the sdk with docstrings --- .../codon-instrumentation-langgraph/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation-packages/codon-instrumentation-langgraph/pyproject.toml b/instrumentation-packages/codon-instrumentation-langgraph/pyproject.toml index 2d7f50e..3f7ec07 100644 --- a/instrumentation-packages/codon-instrumentation-langgraph/pyproject.toml +++ b/instrumentation-packages/codon-instrumentation-langgraph/pyproject.toml @@ -18,7 +18,7 @@ classifiers = [ "Operating System :: OS Independent", ] dependencies = [ - "codon_sdk @ git+https://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@github.com/Codon-Ops/codon-sdk.git#subdirectory=sdk", + "codon_sdk", "opentelemetry-api", "opentelemetry-sdk", "opentelemetry-exporter-otlp-proto-grpc",