Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion python/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ lint:

.PHONY: test
test: update generate-test-certs
uv run pytest ./packages/**/tests/
uv run pytest --import-mode=importlib ./packages/**/tests/ ./samples/langgraph/currency/tests/ ./samples/openai/basic_agent/tests/ ./samples/langgraph/hitl-tools/tests/ ./samples/langgraph/kebab/tests/ ./samples/adk/basic/tests/ ./samples/crewai/research-crew/tests/ ./samples/crewai/poem_flow/tests/

.PHONY: build
build: update format
Expand Down
53 changes: 42 additions & 11 deletions python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,12 @@

## Python

First, set up a virtual environment:
```bash
uv venv .venv
```

We use uv to manage dependencies as well as the python version.
The workspace uses `uv` to manage its Python version, dependencies, and local
`.venv`. From this directory, install the configured Python version and sync the
workspace:

```bash
uv python install
```

Once we have python installed, we can download the dependencies:

```bash
uv sync --all-extras
```

Expand Down Expand Up @@ -67,3 +59,42 @@ In this example, the HTTP listener uses port `8080`. Substrate readiness uses a
separate listener on port `8081`. A2A gRPC binds to `[::]` on `runtime.port`,
which the controller sets to `80`. The same variable selects the Go ADK's
shared HTTP/gRPC port.

## API v2 Inventory

The Python workspace contains these packages:

| Package | Responsibility |
| --- | --- |
| `agentsts-adk` | AgentSTS integration points for ADK |
| `agentsts-core` | OAuth 2.0 token exchange client |
| `kagent-adk` | ADK A2A runtime integration |
| `kagent-core` | Shared Python runtime support |
| `kagent-crewai` | CrewAI A2A runtime integration |
| `kagent-langgraph` | LangGraph A2A runtime integration |
| `kagent-openai` | OpenAI Agents SDK A2A runtime integration |
| `kagent-proto` | Generated protobuf and gRPC contracts |
| `kagent-skills` | Skills discovery and loading |

The retained samples and their installed entry points are:

| Sample | Command |
| --- | --- |
| `adk/basic` | `kagent-adk run basic --working-dir /app --host 0.0.0.0` |
| `crewai/poem_flow` | `poem-flow` |
| `crewai/research-crew` | `research-crew` |
| `langgraph/currency` | `currency` |
| `langgraph/hitl-tools` | `hitl-tools` |
| `langgraph/kebab` | `kebab` |
| `openai/basic_agent` | `basic-openai-agent` |

`make test` verifies package tests plus ASGI construction and `GET /health` for
every listed sample. These checks do not establish container startup, live A2A
requests, deployment, external-model execution, or durable restart behavior.

## Removed REST Session Client

The test suite rejects the removed Kagent-owned Python REST session modules.
Production A2A task history is persisted through the controller gRPC API by
`KAgentTaskStore`. Framework-level conversation state, such as an OpenAI Agents
SDK session or a LangGraph checkpointer, remains the framework's responsibility.
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""Tests for durable-dir session storage: AgentConfig.session_db_url selects the local
DatabaseSessionService instead of controller-backed session storage."""
"""Tests for durable-dir and in-memory ADK session storage."""

from a2a.types import AgentCard
from google.protobuf.json_format import ParseDict
Expand Down Expand Up @@ -29,7 +28,7 @@ def make_kagent_app(agent_config: AgentConfig | None = None) -> KAgentApp:
return KAgentApp(
root_agent_factory=lambda: None,
agent_card=card,
kagent_api_url="http://kagent-controller:8083",
kagent_api_url="http://localhost:8083",
app_name=APP_NAME,
config=Config(agent=agent_config),
)
Expand Down Expand Up @@ -57,7 +56,7 @@ def __init__(self, db_url):
assert constructed == {"db_url": "sqlite+aiosqlite:////data/sessions.db"}


def test_no_url_selects_kagent_session_service(monkeypatch):
def test_no_url_keeps_in_memory_sessions(monkeypatch):
def boom(*args, **kwargs):
raise AssertionError("DatabaseSessionService must not be constructed without a session DB URL")

Expand Down
22 changes: 22 additions & 0 deletions python/packages/kagent-core/tests/test_removed_session_apis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""Guard against removed Kagent-owned Python session APIs."""

from pathlib import Path

import pytest

PYTHON_ROOT = Path(__file__).parents[3]
SOURCE_SUFFIXES = {".py", ".md", ".json", ".yaml", ".yml"}
REMOVED_API_MARKERS = ("KAgent" + "Session", "kagent.openai._session" + "_service")


@pytest.mark.parametrize("marker", REMOVED_API_MARKERS)
def test_python_sources_do_not_reference_removed_kagent_session_apis(marker: str):
matches = []
for directory in (PYTHON_ROOT / "packages", PYTHON_ROOT / "samples"):
for path in directory.rglob("*"):
if path.suffix not in SOURCE_SUFFIXES or ".venv" in path.parts:
continue
if marker in path.read_text(encoding="utf-8"):
matches.append(path.relative_to(PYTHON_ROOT))

assert not matches, f"Removed Kagent session API {marker!r} found in: {matches}"
22 changes: 9 additions & 13 deletions python/packages/kagent-crewai/README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
# KAgent CrewAI Integration

This package provides CrewAI integration for KAgent with A2A (Agent-to-Agent) server support and session-aware memory storage.
This package provides CrewAI integration for KAgent with A2A (Agent-to-Agent) server support.

## Features

- **A2A Server Integration**: Compatible with KAgent's Agent-to-Agent protocol
- **Event Streaming**: Real-time streaming of crew execution events
- **FastAPI Integration**: Ready-to-deploy web server for agent execution
- **Session-aware Memory**: Store and retrieve agent memories scoped by session ID
- **Flow State Persistence**: Save and restore CrewAI Flow states to KAgent backend

## Quick Start

Expand Down Expand Up @@ -54,19 +52,15 @@ research_task:

This is equivalent of `crew.kickoff(inputs={"input": "your input text"})` when triggering agents manually.

### Session-aware Memory
### Memory and Flow State

#### CrewAI Crews

Session scoped memory is implemented using the `LongTermMemory` interface in CrewAI. If you wish to share memories between agents, you must interact with them in the same session to share long term memory so they can search and access the previous conversation history (because agent ID is volatile, we must use session ID). You can enable this by setting `memory=True` when creating your CrewAI crew. Note that this memory is also scoped by user ID so different users will not see each other's memories.

Our KAgent backend is designed to handle long term memory saving and retrieval with the identical logic as `LTMSQLiteStorage` which is used by default for `LongTermMemory` in CrewAI, with the addition of session and user scoping. It will search the LTM items based on the task description and return the most relevant items (sorted and limited).

> Note that when you set `memory=True`, you are responsible to ensure that short term and entity memory are configured properly (e.g. with `OPENAI_API_KEY` or set your own providers). The KAgent CrewAI integration only handles long term memory.
`KAgentApp` does not configure or persist CrewAI memory. Configure CrewAI memory and its backing storage explicitly when your application needs it.

#### CrewAI Flows

In flow mode, we implement memory similar to checkpointing in LangGraph so that the flow state is persisted to the KAgent backend after each method finishes execution. We consider each session to be a single flow execution, so you can reuse state within the same session by enabling `@persist()` for flow or methods. We do not manage `LongTermMemory` for crews inside a flow since flow is designed to be very customizable. You are responsible for implementing your own memory management for all the crew you use in the flow.
`KAgentApp` creates a Flow instance for each A2A request. It does not persist Flow state or restore it for later requests. Configure persistence in your Flow application when needed.

### Tracing

Expand All @@ -79,17 +73,19 @@ The package mirrors the structure of `kagent-adk` and `kagent-langgraph` but use
- **CrewAIAgentExecutor**: Executes CrewAI workflows within A2A protocol
- **KAgentApp**: FastAPI application builder with A2A integration
- **Event Converters**: Translates CrewAI events into A2A events for streaming.
- **Task history**: The public A2A gateway persists client-visible task and event history.
- **KAgentTaskStore**: Persists public A2A task history through the controller gRPC API.

For local development, configure the HTTP endpoint used by protocol traffic:
For local development, provide the runtime configuration described below.

```bash
# Load process settings from /config/config.json (see Configuration).
```

## Deployment

The uses the same deployment approach as other KAgent A2A applications (ADK / LangGraph). You can refer to `samples/crewai/` for examples.
Use the `samples/crewai/` applications as deployment examples. This package does
not configure CrewAI memory or Flow persistence; applications that need either
must provide their own backing storage.

### Runtime configuration file

Expand Down
47 changes: 23 additions & 24 deletions python/packages/kagent-langgraph/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,29 @@ This package provides LangGraph integration for KAgent with A2A (Agent-to-Agent)

## Features

- **A2A Server Integration**: Compatible with KAgent's Agent-to-Agent protocol
- **Event Streaming**: Real-time streaming of graph execution events
- **FastAPI Integration**: Ready-to-deploy web server for agent execution
- **A2A Server Integration**: Serves LangGraph workflows over A2A
- **Event Streaming**: Streams graph execution events
- **FastAPI Integration**: Builds a deployable FastAPI application

## Quick Start

```python
from kagent.core import AsyncControllerClient, AsyncFileTokenProvider, KAgentConfig
from kagent.langgraph import KAgentApp
import os
import sqlite3
from typing import Annotated, Sequence, TypedDict

from kagent.core import KAgentConfig
from kagent.langgraph import KAgentApp
from langchain_core.messages import BaseMessage
from langgraph.checkpoint.sqlite import SqliteSaver
from langgraph.graph import StateGraph
from langchain_core.messages import BaseMessage
from typing import TypedDict, Annotated, Sequence


class State(TypedDict):
messages: Annotated[Sequence[BaseMessage], "The conversation history"]


config = KAgentConfig.from_file()
controller_client = AsyncControllerClient(
config.grpc_url,
agent_name=config.app_name,
token_provider=AsyncFileTokenProvider(),
)

# Define and compile your graph
builder = StateGraph(State)
# Add nodes and edges...
checkpointer = SqliteSaver(
Expand All @@ -43,32 +37,37 @@ checkpointer = SqliteSaver(
)
graph = builder.compile(checkpointer=checkpointer)

# Create KAgent app
app = KAgentApp(
graph=graph,
agent_card={
"name": "my-langgraph-agent",
"description": "A LangGraph agent with KAgent integration",
"version": "0.1.0",
"supportedInterfaces": [{"url": "http://localhost:8080", "protocolBinding": "JSONRPC"}],
"capabilities": {"streaming": True},
"defaultInputModes": ["text"],
"defaultOutputModes": ["text"],
"defaultInputModes": ["text/plain"],
"defaultOutputModes": ["text/plain"],
},
config=config,
controller_client=controller_client,
)

# Build FastAPI application
fastapi_app = app.build()
```

## Architecture
## State and Task Storage

The LangGraph checkpointer owns graph conversation state. A SQLite checkpointer stores checkpoints in a local file; persistence across pod replacement requires placing that file on durable storage or selecting another durable LangGraph checkpointer.

The package mirrors the structure of `kagent-adk` but uses LangGraph instead of Google's ADK:
`KAgentApp` persists public A2A task history through `KAgentTaskStore` and the
controller gRPC API. This task history is separate from LangGraph conversation
state; configuring one does not make the other durable.

## Architecture

- **LangGraphAgentExecutor**: Executes LangGraph workflows within A2A protocol
- **KAgentApp**: FastAPI application builder with A2A integration
- **Task Management**: Automatic A2A task persistence through one shared authenticated gRPC channel
- **LangGraphAgentExecutor**: Executes LangGraph workflows over A2A
- **KAgentApp**: Builds the FastAPI A2A application
- **LangGraph checkpointer**: Stores graph conversation state when configured
- **KAgentTaskStore**: Persists public A2A task history through controller gRPC

## Configuration

Expand Down
Loading