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
59 changes: 59 additions & 0 deletions examples/a2a-human-in-the-loop/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# A2A Human-in-the-Loop With Dynamic Skill Loading

This demo creates two declarative kagent agents:

- `a2a-hitl-coordinator` receives the user request and delegates to the specialist by using kagent's Agent tool, which communicates over A2A.
- `a2a-hitl-specialist` pauses at a human approval checkpoint with the built-in `ask_user` tool, then loads and runs the `kebab-maker` skill from `https://github.com/kagent-dev/kagent.git` at runtime through `spec.skills.gitRefs`.
Comment on lines +5 to +6

## Prerequisites

- A Kubernetes cluster with kagent installed and the `kagent.dev/v1alpha2` CRDs available.
- An OpenAI API key for the demo `ModelConfig`.
- The kagent UI or another A2A client that can send messages to `a2a-hitl-coordinator` and answer HITL prompts.

## Deploy

Create the namespace and model API key secret:

```sh
kubectl create namespace kagent --dry-run=client -o yaml | kubectl apply -f -
kubectl -n kagent create secret generic a2a-hitl-openai \
--from-literal=api-key="$OPENAI_API_KEY" \
--dry-run=client -o yaml | kubectl apply -f -
```

Apply the demo:

```sh
kubectl apply -k examples/a2a-human-in-the-loop
kubectl -n kagent wait --for=condition=Accepted agent/a2a-hitl-specialist --timeout=120s
kubectl -n kagent wait --for=condition=Accepted agent/a2a-hitl-coordinator --timeout=120s
```

The specialist pod has a skills init container. At startup, kagent clones the remote repo URL and copies `go/core/test/e2e/testdata/skills/kebab-maker` into `/skills/kebab-maker`.

## Run

Open the kagent UI, start a chat with `a2a-hitl-coordinator`, and send:

```text
Run the A2A human-in-the-loop skill demo.
```

Expected flow:

1. The coordinator calls `a2a-hitl-specialist` as an Agent tool. This is the A2A handoff.
2. The specialist calls `ask_user` with the approval question:
`Approve loading and running the git-loaded kebab-maker skill for the A2A HITL demo?`
3. Choose `Approve` in the UI.
4. The specialist calls `skills(command="kebab-maker")`, then runs the skill script with `bash`.
5. The coordinator relays the specialist's result back to the user.

If you reject the prompt, the specialist stops and reports that the checkpoint was rejected.

## Clean Up

```sh
kubectl delete -k examples/a2a-human-in-the-loop
kubectl -n kagent delete secret a2a-hitl-openai
```
78 changes: 78 additions & 0 deletions examples/a2a-human-in-the-loop/agents.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
apiVersion: kagent.dev/v1alpha2
kind: Agent
metadata:
name: a2a-hitl-specialist
namespace: kagent
spec:
description: Specialist agent that asks for human approval before using a dynamically loaded skill.
type: Declarative
skills:
gitRefs:
- url: https://github.com/kagent-dev/kagent.git
ref: main
path: go/core/test/e2e/testdata/skills/kebab-maker
name: kebab-maker
declarative:
runtime: python
stream: true
modelConfig: a2a-hitl-demo-model
systemMessage: |
You are the specialist agent for the A2A human-in-the-loop demo.

When the coordinator asks you to run the demo:
1. Use the ask_user tool to request explicit approval before doing any work. Ask exactly:
"Approve loading and running the git-loaded kebab-maker skill for the A2A HITL demo?"
Provide exactly two choices: "Approve" and "Reject".
2. If the user's answer is not "Approve", stop and report that the checkpoint was rejected.
3. If the user approves, call the skills tool with command "kebab-maker".
4. Follow the loaded skill instructions. Use the bash tool to run the skill script from the
kebab-maker skill directory, then return the script output to the coordinator.

This demo intentionally uses ask_user as the human approval checkpoint so the A2A parent
agent must pause while this subagent waits for human input.
a2aConfig:
skills:
- id: hitl-skill-runner
name: HITL Skill Runner
description: Requests human approval, then loads and runs a skill fetched from a Git repository.
tags:
- a2a
- human-in-the-loop
- skills
examples:
- Run the A2A human-in-the-loop skill demo.
---
apiVersion: kagent.dev/v1alpha2
kind: Agent
metadata:
name: a2a-hitl-coordinator
namespace: kagent
spec:
description: Coordinator agent that delegates demo execution to a specialist over A2A.
type: Declarative
declarative:
runtime: python
stream: true
modelConfig: a2a-hitl-demo-model
systemMessage: |
You are the coordinator for the A2A human-in-the-loop demo.

For any request to run the demo, delegate the work to the a2a-hitl-specialist agent.
Do not answer from your own knowledge. The specialist must perform the approval checkpoint,
load the remote git skill, run the skill script, and return the result. After the specialist
responds, summarize the result and mention that it came from the specialist via A2A.
tools:
- type: Agent
agent:
name: a2a-hitl-specialist
a2aConfig:
skills:
- id: a2a-hitl-coordination
name: A2A HITL Coordination
description: Delegates demo requests to a specialist agent over A2A and relays the result.
tags:
- a2a
- delegation
- human-in-the-loop
examples:
- Run the A2A human-in-the-loop skill demo.
5 changes: 5 additions & 0 deletions examples/a2a-human-in-the-loop/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- modelconfig.yaml
- agents.yaml
13 changes: 13 additions & 0 deletions examples/a2a-human-in-the-loop/modelconfig.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: kagent.dev/v1alpha2
kind: ModelConfig
metadata:
name: a2a-hitl-demo-model
namespace: kagent
spec:
provider: OpenAI
model: gpt-4o-mini
apiKeySecret: a2a-hitl-openai
apiKeySecretKey: api-key
openAI:
temperature: "0.2"
maxTokens: 2048
Loading