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
56 changes: 44 additions & 12 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 All @@ -29,4 +21,44 @@ The python code in this project uses the UV workspaces to manage the dependencie

The package directory contains various sub-packages which comprise the kagent engine. Each framework which kagent supports has its own package.

In addition there is a top-level kagent package which contains the main entry point for the engine. In the future we may want to have separate entrypoints for each framework to reduce the number of dependencies we have to install.
In addition there is a top-level kagent package which contains the main entry point for the engine. In the future we may want to have separate entrypoints for each framework to reduce the number of dependencies we have to install.

## 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.

## Legacy Session References

The test suite rejects the removed Kagent-owned REST session APIs. Remaining uses
of "session" are framework-local: OpenAI SDK session factories, ADK's in-memory
or SQLite `DatabaseSessionService`, ADK remote-agent isolation, and temporary
skills working directories. They do not identify or call a Kagent-owned REST
session API.
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,
agent_config=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", "_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}"
20 changes: 7 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 @@ -49,19 +47,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 @@ -74,9 +68,9 @@ 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.
- **Task store**: Tracks A2A tasks in memory for the lifetime of the application process.

For local development, configure the HTTP endpoint used by protocol traffic:
`KAgentConfig` requires its configuration values, but this wrapper does not use `KAGENT_API_URL` or `KAGENT_GATEWAY_URL` for outbound connections. For local development, configure the required values:

```bash
export KAGENT_API_URL=http://localhost:8083
Expand All @@ -87,4 +81,4 @@ export KAGENT_NAMESPACE=default

## 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 provide a Kagent-backed memory or Flow-persistence service.
69 changes: 12 additions & 57 deletions python/packages/kagent-langgraph/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,71 +4,26 @@ 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
## State and Task Storage

```python
from kagent.core import AsyncControllerClient, AsyncFileTokenProvider, KAgentConfig
from kagent.langgraph import KAgentApp
import os
import sqlite3
from langgraph.checkpoint.sqlite import SqliteSaver
from langgraph.graph import StateGraph
from langchain_core.messages import BaseMessage
from typing import TypedDict, Annotated, Sequence
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.

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

config = KAgentConfig()
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(sqlite3.connect(
os.getenv("KAGENT_CHECKPOINT_DB", "/tmp/langgraph-checkpoints.sqlite"),
check_same_thread=False,
))
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",
"capabilities": {"streaming": True},
"defaultInputModes": ["text"],
"defaultOutputModes": ["text"]
},
config=config,
controller_client=controller_client,
)

# Build FastAPI application
fastapi_app = app.build()
```
`KAgentApp` uses an in-memory A2A task store inside the agent process. That task state does not survive a process restart. This package does not configure a gateway connection; a deployment may place a gateway in front of the application and have that gateway own durable task history.

## Architecture

The package mirrors the structure of `kagent-adk` but uses LangGraph instead of Google's ADK:

- **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
- **InMemoryTaskStore**: Tracks A2A tasks for the lifetime of the process

## Configuration

Set both endpoints when running locally. A2A and MCP use `KAGENT_GATEWAY_URL`, while control-plane calls use `KAGENT_API_URL`.
`KAgentConfig` currently requires both endpoint values and the agent identity. This wrapper uses the identity and tracing configuration, but does not use these URLs for outbound control-plane or gateway calls:

```bash
export KAGENT_API_URL=http://localhost:8083
Expand All @@ -79,4 +34,4 @@ export KAGENT_NAMESPACE=default

## Deployment

Use the same deployment pattern as kagent-adk samples with Docker and Kubernetes.
This package has no documented end-to-end deployment path yet. Sample documentation identifies the validation available for each sample.
Loading
Loading