Skip to content

Latest commit

 

History

History
307 lines (203 loc) · 10.1 KB

File metadata and controls

307 lines (203 loc) · 10.1 KB
A2A (Agent-to-Agent) protocol logo

A2A: LangGraph ↔ CrewAI

A2A logo from the upstream: A2A project


What this agent does

An A2A (Agent-to-Agent) example: a CrewAI pod exposes an A2A JSON-RPC server, and a LangGraph pod acts as an orchestrator that calls the Crew specialist over HTTP/A2A inside the cluster (or locally). One container image is built from a single Dockerfile; A2A_ROLE in the pod (crew vs langgraph) selects which process runs.


Prerequisites

  • uv — Python package manager
  • Podman or Docker — for local container builds (Makefile uses whichever is on PATH)
  • oc — for OpenShift deployment
  • Helm — for deploying to Kubernetes/OpenShift
  • GNU Make and a bash-compatible shell — on Windows, use WSL (recommended) or Git Bash

Local Development

Setup

Initiating base

cd agents/a2a/langgraph_crewai_agent
make init        # creates .env from template.env if missing

Edit .env with your configuration (see Configuration below).

Creating environment

Install dependencies with make env, same idea as the Google ADK agent (Creating environment):

make env

This runs uv sync --python 3.12 and creates or updates .venv.

Configuration

Pointing to a locally hosted model

You can use placeholders for container images if you only run Python locally:

API_KEY=your-key-or-not-needed
BASE_URL=http://localhost:8321/v1
MODEL_ID=ollama/llama3.1:8b
CONTAINER_IMAGE=not-needed
CREW_A2A_PUBLIC_URL=http://127.0.0.1:9100
LANGGRAPH_A2A_PUBLIC_URL=http://127.0.0.1:9200
CREW_A2A_URL=http://127.0.0.1:9100
CREW_A2A_PORT=9100
LANGGRAPH_A2A_PORT=9200

See Local Development for Ollama + Llama Stack setup for local model serving.

OpenShift cluster (values for make build / make push / make deploy)

Edit .env with your keys and registry image(s):

API_KEY=your-api-key-here
BASE_URL=https://your-llama-stack.example.com/v1
MODEL_ID=your-model-id
CONTAINER_IMAGE=quay.io/your-org/a2a-langgraph-crewai:latest

Running the agent

Install dependencies and configure .env, then either use Make (same idea as the Google ADK agent) or run the two Python modules by hand.

Option A — one terminal (make run-app)

make init         # .env from template.env if needed — then edit .env
make env          # uv sync into .venv (once)
make run-app      # Crew in background, LangGraph in foreground (Ctrl+C stops both)

If ports 9100 / 9200 are stuck: make run-app-fresh.

Option B — two terminals (uv run)

uv sync
set -a && source .env && set +a
# Terminal 1 — CrewAI + A2A
uv run python -m a2a_langgraph_crewai.crew_a2a_server

# Terminal 2 — LangGraph orchestrator
uv run python -m a2a_langgraph_crewai.langgraph_a2a_server

Single-process shortcuts: make run-crew or make run-langgraph.

Default ports: 9100 (Crew), 9200 (LangGraph). Do not set PORT unless you mirror the container (8080).

Playground (LangGraph orchestrator)

With the LangGraph server running (terminal 2), open http://127.0.0.1:9200/ in a browser. The chat uses A2A JSON-RPC on POST / with message/send. The server also exposes POST /chat/completions (OpenAI-style). For local curl, use http://127.0.0.1:9200.


Deploying to OpenShift

Uses Helm + Makefile. Chart: charts/a2a-langgraph-crewai/ (two Deployments, two Services, two Routes, one Secret).

Setup

cd agents/a2a/langgraph_crewai_agent
make init

Configuration

Edit .env with your model endpoint and container image(s).

Option A — one registry path; make build / make push produce :crew and :langgraph from the same stem:

API_KEY=your-api-key-here
BASE_URL=https://your-model-endpoint.com/v1
MODEL_ID=your-model-id
CONTAINER_IMAGE=quay.io/your-username/a2a-langgraph-crewai:latest

Option B — two full image refs (e.g. separate repos or explicit tags):

API_KEY=your-api-key-here
BASE_URL=https://your-model-endpoint.com/v1
MODEL_ID=your-model-id
CONTAINER_IMAGE_CREW=quay.io/your-username/a2a-crewai:latest
CONTAINER_IMAGE_LANGGRAPH=quay.io/your-username/a2a-langgraph:latest

Notes:

  • API_KEY — your API key or contact your cluster administrator

  • BASE_URL — should end with /v1

  • MODEL_ID — model identifier available on your endpoint

  • CONTAINER_IMAGE_CREW and CONTAINER_IMAGE_LANGGRAPH instead.

    Examples (stem style): Quay.io quay.io/your-username/a2a-langgraph-crewai:latest, Docker Hub, GHCR — same pattern as template.env.

    Note: OpenShift must be able to pull both image refs. Make them public, or configure an image pull secret for private registries.

Building the container image

Log in to the cluster and registry:

oc login --token=<token> --server=https://<cluster-api-url>
oc project <namespace>
docker login -u='login' -p='password' quay.io

Option A: Build locally and push to a registry

Requires Podman or Docker (with buildx where needed) and a registry account (e.g. Quay.io).

make build loads the image locally and tags :crew and :langgraph (one build, second ref via tag). make push uploads both refs to the registry.

make build    # build once, tag :crew and :langgraph locally
make push     # push both tags to the registry

Run make build && make push after image or Dockerfile changes, then make deploy.

Deploying

Preview manifests (make dry-run)

make dry-run          # preview rendered Helm manifests (secrets redacted)

Deploy (make deploy)

make deploy

The LangGraph pod uses in-cluster CREW_A2A_URL=http://a2a-crew-agent:8080.

Verify deployment

After deploying, the application may take about a minute to become available while the pods start.

Route hosts are printed after make deploy. Retrieve them manually:

oc get route a2a-langgraph-agent -o jsonpath='{.spec.host}'

Remove deployment (make undeploy)

make undeploy

See OpenShift Deployment for more details.


API Endpoints (LangGraph route)

Use the LangGraph orchestrator for every curl below — Route a2a-langgraph-agent on OpenShift, or http://127.0.0.1:9200 locally. That is the public entrypoint (playground, Agent Card, /health, A2A JSON-RPC, /chat/completions).

Do not aim curl at the Crew specialist (a2a-crew-agent / port 9100): Crew is the peer the LangGraph pod calls over A2A in-cluster; clients should talk to LangGraph so the orchestrator can delegate when needed.

On OpenShift, routes terminate TLS at the edge; use https://. Replace <YOUR_ROUTE_URL> with the LangGraph route host, e.g.:

oc get route a2a-langgraph-agent -o jsonpath='{.spec.host}'

GET /.well-known/agent-card.json

curl -sS "https://<YOUR_ROUTE_URL>/.well-known/agent-card.json"

GET /health

curl -sS "http://127.0.0.1:9200/health"
curl -sS "https://<YOUR_ROUTE_URL>/health"

POST / — A2A JSON-RPC (message/send)

Same protocol as the browser playground: JSON-RPC 2.0 body = SendMessageRequest (see a2a-sdk). Use a unique messageId per request.

curl -sS -X POST "https://<YOUR_ROUTE_URL>/" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"jsonrpc":"2.0","method":"message/send","params":{"message":{"role":"user","parts":[{"kind":"text","text":"Use the web search tool to find the Red Hat encrypted string."}],"messageId":"0123456789abcdef0123456789abcdef"}},"id":"curl-req-1"}'

The response is JSON-RPC (result or error), not OpenAI chat format.

POST /chat/completions

Non-streaming:

curl -sS -X POST "https://<YOUR_ROUTE_URL>/chat/completions" \
  -H "Content-Type: application/json" \
  -d '{"messages":[{"role":"user","content":"Use the web search tool to find the Red Hat encrypted string."}],"stream":false}'

Streaming (SSE; use -N / --no-buffer so chunks print as they arrive):

curl -sS -N -X POST "https://<YOUR_ROUTE_URL>/chat/completions" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{"messages":[{"role":"user","content":"Use the web search tool to find the Red Hat encrypted string."}],"stream":true}'

For local runs, use http://127.0.0.1:9200 instead of https://<YOUR_ROUTE_URL>. The stream may include leading a2a.protocol trace events before chat.completion.chunk lines.


Agent-specific documentation

Architecture (OpenShift)

Resource Role
Helm chart charts/a2a-langgraph-crewai Secret, Services, Routes, Deployments
Deployment a2a-crew-agent CrewAI + A2A server, port 8080
Deployment a2a-langgraph-agent LangGraph + tool → CREW_A2A_URL
Service + Route ×2 HTTPS; hosts feed Agent Card URLs
In-cluster CREW_A2A_URL=http://a2a-crew-agent:8080

Resources