Tutorial: A2A Client
Discover an A2A agent and send messages using the runtime client.
Time: 10 minutes Level: Intermediate
What You’ll Build
Section titled “What You’ll Build”A client that discovers a remote A2A agent and sends messages — both synchronous and streaming.
What You’ll Learn
Section titled “What You’ll Learn”- Create an A2A client
- Discover an agent’s capabilities via its agent card
- Send synchronous messages
- Receive streaming events
Prerequisites
Section titled “Prerequisites”- Go 1.22+
- A running A2A server (see A2A Server Tutorial)
Step 1: Create the Client
Section titled “Step 1: Create the Client”package main
import ( "context" "fmt" "log"
"github.com/AltairaLabs/PromptKit/runtime/a2a")
func main() { ctx := context.Background() client := a2a.NewClient("http://localhost:9999")You can configure the client with options:
client := a2a.NewClient("http://localhost:9999", a2a.WithAuth("Bearer", "my-token"), a2a.WithHTTPClient(customHTTPClient),)Step 2: Discover the Agent
Section titled “Step 2: Discover the Agent”Fetch the agent card to learn what the agent can do:
card, err := client.Discover(ctx) if err != nil { log.Fatalf("Discover: %v", err) }
fmt.Printf("Agent: %s\n", card.Name) fmt.Printf("Description: %s\n", card.Description) for _, skill := range card.Skills { fmt.Printf(" Skill: %s — %s\n", skill.ID, skill.Description) }The card is cached after the first call, so subsequent Discover calls are free.
Step 3: Send a Message
Section titled “Step 3: Send a Message”Send a synchronous message with Blocking: true:
text := "Hello from the client!" task, err := client.SendMessage(ctx, &a2a.SendMessageRequest{ Message: a2a.Message{ Role: a2a.RoleUser, Parts: []a2a.Part{{Text: &text}}, }, Configuration: &a2a.SendMessageConfiguration{Blocking: true}, }) if err != nil { log.Fatalf("SendMessage: %v", err) }
fmt.Printf("Task state: %s\n", task.Status.State) for _, artifact := range task.Artifacts { for _, part := range artifact.Parts { if part.Text != nil { fmt.Printf("Agent: %s\n", *part.Text) } } }Expected output:
Agent: Echo AgentDescription: Echoes back whatever you send Skill: echo — Echoes the input message backTask state: completedAgent: Echo: Hello from the client!Step 4: Try Streaming
Section titled “Step 4: Try Streaming”Use SendMessageStream to receive incremental updates:
streamText := "Tell me a story" events, err := client.SendMessageStream(ctx, &a2a.SendMessageRequest{ Message: a2a.Message{ Role: a2a.RoleUser, Parts: []a2a.Part{{Text: &streamText}}, }, }) if err != nil { log.Fatalf("Stream: %v", err) }
for event := range events { if event.StatusUpdate != nil { fmt.Printf("[status] %s\n", event.StatusUpdate.Status.State) } if event.ArtifactUpdate != nil { for _, part := range event.ArtifactUpdate.Artifact.Parts { if part.Text != nil { fmt.Print(*part.Text) } } } } fmt.Println()}Streaming requires the server to support it. If the server doesn’t support streaming, you’ll see a single artifact event followed by completion.
Step 5: Manage Tasks
Section titled “Step 5: Manage Tasks”Retrieve or cancel tasks by ID:
// Get a task by ID.task, err := client.GetTask(ctx, "task-123")
// Cancel a running task.err = client.CancelTask(ctx, "task-123")
// List tasks by context.tasks, err := client.ListTasks(ctx, &a2a.ListTasksRequest{ ContextID: "ctx-456",})What You’ve Learned
Section titled “What You’ve Learned”- How to create an A2A client and configure authentication
- How to discover agents via their agent card
- How to send synchronous and streaming messages
- How to manage tasks (get, cancel, list)
Next Steps
Section titled “Next Steps”- A2A Server Tutorial — build the server side
- Use Tool Bridge — register this agent as a tool
- Use Mock Server — test without a real server
- A2A Concept — understand the protocol in depth
See Also
Section titled “See Also”- Runtime A2A Reference — complete client API documentation
- Examples — full working examples