# null Source: https://docs.agentwire.io/concepts/agents # Core architecture Source: https://docs.agentwire.io/concepts/architecture Understand how AWP connects front-end applications to AI agents Agent Wire Protocol (AWP) is built on a flexible, event-driven architecture that enables seamless, efficient communication between front-end applications and AI agents. This document covers the core architectural components and concepts. ## Overview AWP follows a client-server architecture that standardizes communication between agents and applications: ```mermaid flowchart LR subgraph "Frontend" App["Application"] Client["AWP Client"] end subgraph "Backend" A1["AI Agent A"] P["Secure Proxy"] A2["AI Agent B"] A3["AI Agent C"] end App <--> Client Client <-->|"Agent Wire Protocol"| A1 Client <-->|"Agent Wire Protocol"| P P <-->|"Agent Wire Protocol"| A2 P <-->|"Agent Wire Protocol"| A3 class P mintStyle; classDef mintStyle fill:#E0F7E9,stroke:#66BB6A,stroke-width:2px,color:#000000; style App rx:5, ry:5; style Client rx:5, ry:5; style A1 rx:5, ry:5; style P rx:5, ry:5; style A2 rx:5, ry:5; style A3 rx:5, ry:5; ``` * **Application**: User-facing apps (i.e. chat or any AI-enabled application). * **AWP Client**: Generic communication clients like `HttpAgent` or specialized clients for connecting to existing protocols. * **Agents**: Backend AI agents that process requests and generate streaming responses. * **Secure Proxy**: Backend services that provide additional capabilities and act as a secure proxy. ## Core components ### Protocol layer AWP's protocol layer provides a flexible foundation for agent communication. * **Universal compatibility**: Connect to any protocol by implementing `run(input: RunAgentInput) -> Observable` The protocol's primary abstraction enables applications to run agents and receive a stream of events: {/* prettier-ignore */} ```typescript // Core agent execution interface type RunAgent = () => Observable class MyAgent extends AbstractAgent { run(input: RunAgentInput): RunAgent { const { threadId, runId } = input return () => from([ { type: EventType.RUN_STARTED, threadId, runId }, { type: EventType.MESSAGES_SNAPSHOT, messages: [ { id: "msg_1", role: "assistant", content: "Hello, world!" } ], }, { type: EventType.RUN_FINISHED, threadId, runId }, ]) } } ``` ### Standard HTTP client AWP offers a standard HTTP client `HttpAgent` that can be used to connect to any endpoint that accepts POST requests with a body of type `RunAgentInput` and sends a stream of `BaseEvent` objects. `HttpAgent` supports the following transports: * **HTTP SSE (Server-Sent Events)** * Text-based streaming for wide compatibility * Easy to read and debug * **HTTP binary protocol** * Highly performant and space-efficient custom transport * Robust binary serialization for production environments ### Message types AWP defines several event categories for different aspects of agent communication: * **Lifecycle events** * `RUN_STARTED`, `RUN_FINISHED`, `RUN_ERROR` * `STEP_STARTED`, `STEP_FINISHED` * **Text message events** * `TEXT_MESSAGE_START`, `TEXT_MESSAGE_CONTENT`, `TEXT_MESSAGE_END` * **Tool call events** * `TOOL_CALL_START`, `TOOL_CALL_ARGS`, `TOOL_CALL_END` * **State management events** * `STATE_SNAPSHOT`, `STATE_DELTA`, `MESSAGES_SNAPSHOT` * **Special events** * `RAW`, `CUSTOM` ## Running Agents To run an agent, you create a client instance and execute it: ```typescript // Create an HTTP agent client const agent = new HttpAgent({ url: "https://your-agent-endpoint.com/agent", agentId: "unique-agent-id", threadId: "conversation-thread" }); // Start the agent and handle events agent.runAgent({ tools: [...], context: [...] }).subscribe({ next: (event) => { // Handle different event types switch(event.type) { case EventType.TEXT_MESSAGE_CONTENT: // Update UI with new content break; // Handle other event types } }, error: (error) => console.error("Agent error:", error), complete: () => console.log("Agent run complete") }); ``` ## State Management AWP provides efficient state management through specialized events: * `STATE_SNAPSHOT`: Complete state representation at a point in time * `STATE_DELTA`: Incremental state changes using JSON Patch format (RFC 6902) * `MESSAGES_SNAPSHOT`: Complete conversation history These events enable efficient client-side state management with minimal data transfer. ## Tools and Handoff AWP supports agent-to-agent handoff and tool usage through standardized events: * Tool definitions are passed in the `runAgent` parameters * Tool calls are streamed as sequences of `TOOL_CALL_START` → `TOOL_CALL_ARGS` → `TOOL_CALL_END` events * Agents can hand off to other agents, maintaining context continuity ## Events All communication in AWP is based on typed events. Every event inherits from `BaseEvent`: ```typescript interface BaseEvent { type: EventType timestamp?: number rawEvent?: any } ``` Events are strictly typed and validated, ensuring reliable communication between components. # null Source: https://docs.agentwire.io/concepts/events # null Source: https://docs.agentwire.io/concepts/messages # null Source: https://docs.agentwire.io/concepts/state # null Source: https://docs.agentwire.io/concepts/tools # Contributing Source: https://docs.agentwire.io/development/contributing How to participate in Agent Wire Protocol development For questions and discussions, please use [GitHub Discussions](https://github.com/orgs/agentwire/discussions). # Roadmap Source: https://docs.agentwire.io/development/roadmap Our plans for evolving Agent Wire Protocol The Agent Wire Protocol is rapidly evolving. This page outlines our current thinking on key priorities and future direction. The ideas presented here are not commitments—we may solve these challenges differently than described, or some may not materialize at all. This is also not an *exhaustive* list; we may incorporate work that isn't mentioned here. ## Get Involved We welcome community participation in shaping AWP's future. Visit our [GitHub Discussions](https://github.com/orgs/agentwire/discussions) to join the conversation and contribute your ideas. # What's New Source: https://docs.agentwire.io/development/updates The latest updates and improvements to AWP * Initial release of the Agent Wire Protocol # Integrations Source: https://docs.agentwire.io/integrations A list of AWP integrations This page showcases various Agent Wire Protocol (AWP) integrations that demonstrate the protocol's capabilities and versatility. ## Frontend Integrations * **[CopilotKit](https://copilotkit.ai)** - AI Copilots for your product. ## Agent Frameworks * **[Mastra](https://mastra.ai)** - The TypeScript Agent Framework * **[LangGraph](https://www.langchain.com/langgraph)** - Balance agent control with agency * **[CrewAI](https://crewai.com)** - Streamline workflows across industries with powerful AI agents. * **[AG2](https://ag2.ai)** - The Open-Source AgentOS Visit our [GitHub Discussions](https://github.com/orgs/agentwire/discussions) to engage with the AWP community. # Introduction Source: https://docs.agentwire.io/introduction Get started with the Agent Wire Protocol (AWP) **AWP** standardizes how **front-end applications connect to AI agents** through an open protocol. Think of it as a universal translator for AI-driven systems- no matter what language an agent speaks: **AWP ensures fluent communication**. ## Why AWP? AWP helps developers build next-generation AI workflows that need **real-time interactivity**, **live state streaming** and **human-in-the-loop collaboration**. AWP provides: * **A straightforward approach** to integrating AI agents with the front-end through frameworks such as [CopilotKit 🪁](https://github.com/CopilotKit/CopilotKit) * **Building blocks** for an efficient wire protocol for human⚡️agent communication * **Best practices** for chat, streaming state updates, human-in-the-loop and shared state ### Architecture At its core, AWP bridges AI agents and front-end applications using a lightweight, event-driven protocol: ```mermaid flowchart LR subgraph "Frontend" FE["Front-end"] end subgraph "Backend" A1["AI Agent A"] P["Secure Proxy"] A2["AI Agent B"] A3["AI Agent C"] end FE <-->|"Agent Wire Protocol"| A1 FE <-->|"Agent Wire Protocol"| P P <-->|"Agent Wire Protocol"| A2 P <-->|"Agent Wire Protocol"| A3 class P mintStyle; classDef mintStyle fill:#E0F7E9,stroke:#66BB6A,stroke-width:2px,color:#000000; %% Apply slight border radius to each node style FE rx:5, ry:5; style A1 rx:5, ry:5; style P rx:5, ry:5; style A2 rx:5, ry:5; style A3 rx:5, ry:5; ``` * **Front-end**: The application (chat or any AI-enabled app) that communicates over AWP * **AI Agent A**: An agent that the front-end can connect to directly without going through the proxy * **Secure Proxy**: An intermediary proxy that securely routes requests from the front-end to multiple AI agents * **Agents B and C**: Agents managed by the proxy service ## Quick Start Choose the path that fits your needs: Implement AWP events directly in your agent framework Connect AWP with existing protocols or custom solutions ## Resources Explore guides, tools, and integrations to help you build, optimize, and extend your AWP implementation. These resources cover everything from practical development workflows to debugging techniques. Discover ready-to-use AWP integrations across popular agent frameworks and platforms Use Cursor to build AWP implementations faster Fix common issues when working with AWP servers and clients ## Explore AWP Dive deeper into AWP's core concepts and capabilities: Understand how AWP connects agents, protocols, and front-ends {/* Expose data and content from your servers to LLMs Create reusable prompt templates and workflows Enable LLMs to perform actions through your server Let your servers request completions from LLMs */} Learn about AWP's communication mechanism ## Contributing Want to contribute? Check out our [Contributing Guide](/development/contributing) to learn how you can help improve AWP. ## Support and Feedback Here's how to get help or provide feedback: * For bug reports and feature requests related to the AWP specification, SDKs, or documentation (open source), please [create a GitHub issue](https://github.com/agentwire) * For discussions or Q\&A about the AWP specification, use the [specification discussions](https://github.com/agentwire/specification/discussions) * For discussions or Q\&A about other AWP open source components, use the [organization discussions](https://github.com/orgs/agentwire/discussions) # Build with AWP Source: https://docs.agentwire.io/quickstart/build Implement AWP events directly in your agent framework In this tutorial, you'll learn how to build an HTTP endpoint that is compatible with the [AWP protocol](https://github.com/agentwire). ## Prerequisites Make sure to have [Python](https://www.python.org/downloads/) and [Poetry](https://python-poetry.org/docs/#installation) installed. ## Setup a New Project with Poetry First, let's create a new project and set up Poetry for dependency management: ```bash poetry new my-endpoint && cd my-endpoint ``` ## Install Dependencies Now, let's install the necessary packages: ```bash poetry add agentwire openai fastapi uvicorn ``` ## Create a Basic Endpoint with FastAPI Create a new file called `my_endpoint/main.py` with the following code: ```python from fastapi import FastAPI, Request import json from agentwire.core.types import RunAgentInput app = FastAPI(title="AWP Endpoint") @app.post("/awp") async def my_endpoint(): return { "message": "Hello World" } if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000) ``` ## Run and Test Your Endpoint Start the server with: ```bash poetry run uvicorn my_endpoint.main:app --reload ``` In another terminal, test your endpoint is running using curl: ```bash curl -X POST http://localhost:8000/awp ``` You should see the following response: ```json { "message": "Hello World" } ``` ## Parsing AWP Input Next let's update our endpoint to properly parse the incoming AWP request using the `RunAgentInput` Pydantic model: ```python from fastapi import FastAPI, Request, HTTPException from agentwire.core import RunAgentInput, Message app = FastAPI(title="AWP Endpoint") @app.post("/awp") async def my_endpoint(input_data: RunAgentInput): thread_id = input_data.thread_id return { "message": "Hello World from " + thread_id } ``` FastAPI automatically validates the incoming request against the RunAgentInput schema. If the request doesn't match the expected format, it will return a 422 Validation Error with details about what went wrong. ## Add Event Streaming AWP supports streaming events using Server-Sent Events (SSE). Let's modify our `/awp` endpoint to stream events back to the client: ```python from fastapi import FastAPI, Request, HTTPException from fastapi.responses import StreamingResponse from agentwire.core import RunAgentInput, Message, EventType, RunStartedEvent, RunFinishedEvent from agentwire.encoder import EventEncoder app = FastAPI(title="AWP Endpoint") @app.post("/awp") async def my_endpoint(input_data: RunAgentInput): async def event_generator(): # Create an event encoder to properly format SSE events encoder = EventEncoder() # Send run started event yield encoder.encode( RunStartedEvent( type=EventType.RUN_STARTED, thread_id=input_data.thread_id, run_id=input_data.run_id ) ) # Send run finished event yield encoder.encode( RunFinishedEvent( type=EventType.RUN_FINISHED, thread_id=input_data.thread_id, run_id=input_data.run_id ) ) return StreamingResponse( event_generator(), media_type="text/event-stream" ) if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000) ``` Awesome! We are already sending `RunStartedEvent` and `RunFinishedEvent` events, which gives us a basic AWP compliant endpoint. Now let's make it do something useful. ## Implementing Basic Chat Let's enhance our endpoint to call OpenAI's API and stream the responses back as AWP events: ```python from fastapi import FastAPI, Request from fastapi.responses import StreamingResponse from agentwire.core import ( RunAgentInput, Message, EventType, RunStartedEvent, RunFinishedEvent, TextMessageStartEvent, TextMessageContentEvent, TextMessageEndEvent ) from agentwire.encoder import EventEncoder import uuid from openai import OpenAI app = FastAPI(title="AWP Endpoint") @app.post("/awp") async def my_endpoint(input_data: RunAgentInput): async def event_generator(): # Create an event encoder to properly format SSE events encoder = EventEncoder() # Send run started event yield encoder.encode( RunStartedEvent( type=EventType.RUN_STARTED, thread_id=input_data.thread_id, run_id=input_data.run_id ) ) # Initialize OpenAI client client = OpenAI() # Generate a message ID for the assistant's response message_id = uuid.uuid4() # Send text message start event yield encoder.encode( TextMessageStartEvent( type=EventType.TEXT_MESSAGE_START, message_id=message_id, role="assistant" ) ) # Create a streaming completion request stream = client.chat.completions.create( model="gpt-3.5-turbo", messages=openai_messages, stream=True ) # Process the streaming response and send content events for chunk in stream: if hasattr(chunk.choices[0].delta, "content") and chunk.choices[0].delta.content: content = chunk.choices[0].delta.content yield encoder.encode( TextMessageContentEvent( type=EventType.TEXT_MESSAGE_CONTENT, message_id=message_id, delta=content ) ) # Send text message end event yield encoder.encode( TextMessageEndEvent( type=EventType.TEXT_MESSAGE_END, message_id=message_id ) ) # Send run finished event yield encoder.encode( RunFinishedEvent( type=EventType.RUN_FINISHED, thread_id=input_data.thread_id, run_id=input_data.run_id ) ) return StreamingResponse( event_generator(), media_type="text/event-stream" ) if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000) ``` You'll need to set your OpenAI API key as an environment variable and then restart the server: ```bash export OPENAI_API_KEY=your-api-key poetry run uvicorn my_endpoint.main:app --reload ``` This implementation creates a fully functional AWP endpoint that processes messages and streams back the responses in real-time. ## Prerequisites Make sure to have [Node.js](https://nodejs.org/) (v16 or later) and [npm](https://www.npmjs.com/) or [yarn](https://yarnpkg.com/) installed. ## Setup a New Project First, let's create a new project and set up npm with TypeScript: ```bash mkdir awp-endpoint && cd awp-endpoint npm init -y npm install typescript ts-node @types/node @types/express --save-dev npx tsc --init ``` ## Install Dependencies Install the necessary packages: ```bash npm install express openai @agentwire/core @agentwire/encoder uuid npm install @types/uuid --save-dev ``` ## Create a Basic Endpoint with Express Create a new file called `src/server.ts` with the following code: ```typescript import express from "express" import { Request, Response } from "express" const app = express() app.use(express.json()) app.post("/awp", (req: Request, res: Response) => { res.json({ message: "Hello World" }) }) app.listen(8000, () => { console.log("Server running on http://localhost:8000") }) ``` ## Run and Test Your Endpoint Start the server with: ```bash npx ts-node src/server.ts ``` In another terminal, test your endpoint is running using curl: ```bash curl -X POST http://localhost:8000/awp ``` You should see the following response: ```json { "message": "Hello World" } ``` ## Parsing AWP Input Next let's update our endpoint to properly parse the incoming AWP request using the `RunAgentInput` schema: ```typescript import express, { Request, Response } from "express" import { RunAgentInputSchema, RunAgentInput } from "@agentwire/core" const app = express() app.use(express.json()) app.post("/awp", (req: Request, res: Response) => { try { // Parse and validate the request body const input: RunAgentInput = RunAgentInputSchema.parse(req.body) res.json({ message: `Hello World from ${input.threadId}` }) } catch (error) { res.status(422).json({ error: (error as Error).message }) } }) app.listen(8000, () => { console.log("Server running on http://localhost:8000") }) ``` Express with zod validation ensures the incoming request conforms to the AWP protocol format. If the request doesn't match the expected format, it will return a 422 Validation Error with details about what went wrong. ## Add Event Streaming AWP supports streaming events using Server-Sent Events (SSE). Let's modify our `/awp` endpoint to stream events back to the client: ```typescript import express, { Request, Response } from "express" import { RunAgentInputSchema, RunAgentInput, EventType } from "@agentwire/core" import { EventEncoder } from "@agentwire/encoder" const app = express() app.use(express.json()) app.post("/awp", async (req: Request, res: Response) => { try { // Parse and validate the request body const input: RunAgentInput = RunAgentInputSchema.parse(req.body) // Set up SSE headers res.setHeader("Content-Type", "text/event-stream") res.setHeader("Cache-Control", "no-cache") res.setHeader("Connection", "keep-alive") // Create an event encoder const encoder = new EventEncoder() // Send run started event const runStarted = { type: EventType.RUN_STARTED, threadId: input.threadId, runId: input.runId, } res.write(encoder.encode(runStarted)) // Send run finished event const runFinished = { type: EventType.RUN_FINISHED, threadId: input.threadId, runId: input.runId, } res.write(encoder.encode(runFinished)) // End the response res.end() } catch (error) { res.status(422).json({ error: (error as Error).message }) } }) app.listen(8000, () => { console.log("Server running on http://localhost:8000") }) ``` ## Implementing Basic Chat Let's enhance our endpoint to call OpenAI's API and stream the responses back as AWP events: ```typescript import express, { Request, Response } from "express" import { RunAgentInputSchema, RunAgentInput, EventType, Message, } from "@agentwire/core" import { EventEncoder } from "@agentwire/encoder" import { OpenAI } from "openai" import { v4 as uuidv4 } from "uuid" const app = express() app.use(express.json()) app.post("/awp", async (req: Request, res: Response) => { try { // Parse and validate the request body const input: RunAgentInput = RunAgentInputSchema.parse(req.body) // Set up SSE headers res.setHeader("Content-Type", "text/event-stream") res.setHeader("Cache-Control", "no-cache") res.setHeader("Connection", "keep-alive") // Create an event encoder const encoder = new EventEncoder() // Send run started event const runStarted = { type: EventType.RUN_STARTED, threadId: input.threadId, runId: input.runId, } res.write(encoder.encode(runStarted)) // Initialize OpenAI client const client = new OpenAI() // Convert AWP messages to OpenAI messages format const openaiMessages = input.messages .filter((msg: Message) => ["user", "system", "assistant"].includes(msg.role), ) .map((msg: Message) => ({ role: msg.role as "user" | "system" | "assistant", content: msg.content || "", })) // Generate a message ID for the assistant's response const messageId = uuidv4() // Send text message start event const textMessageStart = { type: EventType.TEXT_MESSAGE_START, messageId, role: "assistant", } res.write(encoder.encode(textMessageStart)) // Create a streaming completion request const stream = await client.chat.completions.create({ model: "gpt-3.5-turbo", messages: openaiMessages, stream: true, }) // Process the streaming response and send content events for await (const chunk of stream) { if (chunk.choices[0]?.delta?.content) { const content = chunk.choices[0].delta.content const textMessageContent = { type: EventType.TEXT_MESSAGE_CONTENT, messageId, delta: content, } res.write(encoder.encode(textMessageContent)) } } // Send text message end event const textMessageEnd = { type: EventType.TEXT_MESSAGE_END, messageId, } res.write(encoder.encode(textMessageEnd)) // Send run finished event const runFinished = { type: EventType.RUN_FINISHED, threadId: input.threadId, runId: input.runId, } res.write(encoder.encode(runFinished)) // End the response res.end() } catch (error) { res.status(422).json({ error: (error as Error).message }) } }) app.listen(8000, () => { console.log("Server running on http://localhost:8000") }) ``` You'll need to set your OpenAI API key as an environment variable and then start the server: ```bash export OPENAI_API_KEY=your-api-key npx ts-node src/server.ts ``` This implementation creates a fully functional AWP endpoint that processes messages and streams back the responses in real-time. # Connect to AWP Source: https://docs.agentwire.io/quickstart/connect Connect AWP with existing protocols or custom solutions In this tutorial, you'll learn how to resurrect one of the first chatbots in computer science history—**the famous Eliza, originally created in the 1960s**! This not only pays homage to computing's past but also demonstrates how the Agent Wire Protocol (AWP) can integrate seamlessly with any protocol. Let's get started. ## Prerequisites Make sure to have the following installed: * [Node.js](https://nodejs.org/) (v16 or later) * [npm](https://www.npmjs.com/) or [yarn](https://yarnpkg.com/) * [Docker](https://www.docker.com/) * A telnet client (optional, i.e. `brew install telnet`) ## Running Eliza via Docker Let's run Eliza in a Docker container and connect to her via `telnet`. ```bash # Pull and run the Eliza Telnet server docker build -t eliza:latest https://docs.agentwire.io/quickstart/eliza/Dockerfile docker run --rm -it -p 2323:2323 eliza:latest ``` Once the container is running, we can connect to Eliza. ```bash telnet localhost 2323 ``` You should see Eliza greet you with: ``` $ telnet localhost 2323 Trying ::1... Connected to localhost. Escape character is '^]'. ===================================================== ELIZA - The first chatbot (1966) by Joseph Weizenbaum Running via Telnet - Type 'quit' to exit ===================================================== Hello, I'm Eliza. How can I help you today? > How are you? What if I were ? > What if you were? What does this speculation lead to ? > I am not sure to be honest. Do you enjoy being not sure to be honest ? > quit Goodbye. It was nice talking to you! Connection closed by foreign host. ``` Type `quit` to exit Telnet. Congratulations! You've just brought Eliza to life. Now let's connect her to the Agent Wire Protocol. ## Bridge Eliza with AWP Now that we have our Eliza server running, let's show how AWP can connect to any protocol—in this case, the somewhat arcane Telnet protocol. ### Project Setup Let's create a new project for our AWP bridge: ```bash # Create a directory for your project mkdir awp-eliza && cd awp-eliza npm init -y npm install @agentwire/client telnetlib npm install -D typescript ts-node @types/node @types/telnetlib npx tsc --init --target ES2020 --module CommonJS --strict --esModuleInterop --skipLibCheck --outDir dist --rootDir src mkdir src ``` ### AWP Recap The Agent Wire Protocol is a framework that lets you connect agents to clients in a structured, event-driven way. Agents implement the `AbstractAgent` class from `@agentwire/client` and emit events for each piece of content, progress, etc. ### ElizaAgent We'll create a special agent class, `ElizaAgent`, which: 1. Launches a Telnet client to connect to our running Eliza server on localhost:2323. 2. Sends the user's last message to Eliza. 3. Waits for the response, then emits AWP events to deliver that text back. Create a file called `src/eliza-agent.ts`: ```typescript // src/eliza-agent.ts import { AbstractAgent, RunAgent, RunAgentInput, EventType, BaseEvent, RunStartedEventSchema, TextMessageStartEventSchema, TextMessageContentEventSchema, TextMessageEndEventSchema, RunFinishedEventSchema, } from "@agentwire/client" import { Observable } from "rxjs" import * as telnetlib from "telnetlib" export class ElizaAgent extends AbstractAgent { protected run(input: RunAgentInput): RunAgent { // AWP calls `run` each time it wants to generate a response. return () => { // Extract user's latest message const lastUserMessage = [...input.messages].reverse().find((msg) => msg.role === "user") ?.content || "Hello, Eliza" return new Observable((observer) => { // 1) Emit RUN_STARTED observer.next( RunStartedEventSchema.parse({ type: EventType.RUN_STARTED, threadId: input.threadId, runId: input.runId, }), ) // Create a new telnet client const client = telnetlib.createConnection( { host: "127.0.0.1", port: 2323, }, () => { console.log("Connected to Eliza telnet server") }, ) // Wait for initial greeting and prompt client.once("data", () => { // Once we receive the greeting, send the user message client.write(lastUserMessage + "\n") // Wait for the response from Eliza client.once("data", (data) => { // Get the response, removing the prompt let response = data.toString().trim() // Strip the trailing prompt if present if (response.endsWith(">")) { response = response.substring(0, response.length - 1).trim() } // Generate a message ID const messageId = Date.now().toString() // Emit typical AWP message events observer.next( TextMessageStartEventSchema.parse({ type: EventType.TEXT_MESSAGE_START, messageId, }), ) observer.next( TextMessageContentEventSchema.parse({ type: EventType.TEXT_MESSAGE_CONTENT, messageId, delta: response, }), ) observer.next( TextMessageEndEventSchema.parse({ type: EventType.TEXT_MESSAGE_END, messageId, }), ) // Emit RUN_FINISHED and complete observer.next( RunFinishedEventSchema.parse({ type: EventType.RUN_FINISHED, threadId: input.threadId, runId: input.runId, }), ) // Close the telnet connection client.end() observer.complete() }) }) // Handle errors client.on("error", (err) => { console.error("Telnet client error:", err) observer.error(err) }) // Return a cleanup function return () => { if (client) { client.end() } } }) } } } ``` ### Explanation 1. **Connection** We create a TelnetClient and connect to our Eliza Telnet server. 2. **User Message** We find the last user message from the AWP input. If none exists, we default to "Hello, Eliza". 3. **Emitting Events** * `RUN_STARTED` means the agent started processing the request. * `TEXT_MESSAGE_START` / `TEXT_MESSAGE_CONTENT` / `TEXT_MESSAGE_END` together send the agent's textual response to the AWP pipeline. * `RUN_FINISHED` means this run is over. 4. **Round-Trip** * Write the user message to Eliza over Telnet. * Listen for the response from Eliza. * Emit that response as AWP events. ## Putting It All Together Create a main entry point file `src/index.ts` that sets up our AWP agent: ```typescript // src/index.ts import { ElizaAgent } from "./eliza-agent" // Create an instance of our agent const elizaAgent = new ElizaAgent() elizaAgent.messages = [ { id: "1", role: "user", content: "I feel anxious about my job." }, ] // Example: Make a request to Eliza through AWP const run = elizaAgent.runAgent({ runId: "run1", }) ``` Run the application: ```bash npx ts-node src/index.ts ``` ## Bridging AWP to Any Protocol This example demonstrates how to bridge AWP with an existing protocol. The key components are: 1. **AWP Agent Implementation**: Create a class that extends `AbstractAgent` and implements the `run` method. 2. **Implement `run()`**: Set up an agent or connect to an existing protocol. 3. **Manage agent input**: Send the right input to the agent (in our case, it's the user's last message). 4. **Send events**: Handle the agent's response and emit AWP events. You can apply this pattern to connect AWP to virtually any protocol or service: * HTTP/REST APIs * WebSockets * MQTT for IoT devices * any other protocol By following this pattern of creating protocol adapters around your AWP agents, you can make your AI agents available through any communication channel while maintaining a consistent agent implementation. ## Conclusion Congratulations! You've resurrected the first historical chatbot by serving Eliza over Telnet and bridged it to the Agent Wire Protocol. This tutorial demonstrates how easy it is to adopt AWP with any existing protocol—be it Telnet, WebSocket, custom REST calls, or something entirely else. # Overview Source: https://docs.agentwire.io/sdk/js/client/overview Client package overview # @agentwire/client The Agent Wire Protocol Client SDK provides agent connectivity options for AI systems. This package builds on the core types and events to deliver flexible connection methods to agent implementations. ```bash npm install @agentwire/client ``` ## AbstractAgent `AbstractAgent` is the base agent class for implementing custom agent connectivity. Extending this class and implementing `run()` lets you bridge your own service or agent implementation to AWP. * [Configuration](/sdk/js/client/abstract-agent#configuration) - Setup with agent ID, messages, and state * [Core Methods](/sdk/js/client/abstract-agent#core-methods) - Run, abort, and clone functionality * [Protected Methods](/sdk/js/client/abstract-agent#protected-methods) - Extensible hooks for custom implementations * [Properties](/sdk/js/client/abstract-agent#properties) - State and message tracking Base class for creating custom agent connections ## HttpAgent Concrete implementation for HTTP-based agent connectivity: * [Configuration](/sdk/js/client/http-agent#configuration) - URL and header setup * [Methods](/sdk/js/client/http-agent#methods) - HTTP-specific execution and cancellation * [Protected Methods](/sdk/js/client/http-agent#protected-methods) - Customizable HTTP request handling * [Properties](/sdk/js/client/http-agent#properties) - Connection management Ready-to-use HTTP implementation for agent connectivity, using a highly efficient event encoding format # Events Source: https://docs.agentwire.io/sdk/js/core/events Documentation for the events used in the Agent Wire Protocol SDK # Events The Agent Wire Protocol SDK uses a streaming event-based architecture. Events are the fundamental units of communication between agents and the frontend. This section documents the event types and their properties. ## EventType Enum The `EventType` enum defines all possible event types in the system: ```typescript enum EventType { TEXT_MESSAGE_START = "TEXT_MESSAGE_START", TEXT_MESSAGE_CONTENT = "TEXT_MESSAGE_CONTENT", TEXT_MESSAGE_END = "TEXT_MESSAGE_END", TOOL_CALL_START = "TOOL_CALL_START", TOOL_CALL_ARGS = "TOOL_CALL_ARGS", TOOL_CALL_END = "TOOL_CALL_END", STATE_SNAPSHOT = "STATE_SNAPSHOT", STATE_DELTA = "STATE_DELTA", MESSAGES_SNAPSHOT = "MESSAGES_SNAPSHOT", RAW = "RAW", CUSTOM = "CUSTOM", RUN_STARTED = "RUN_STARTED", RUN_FINISHED = "RUN_FINISHED", RUN_ERROR = "RUN_ERROR", STEP_STARTED = "STEP_STARTED", STEP_FINISHED = "STEP_FINISHED", } ``` ## BaseEvent All events inherit from the `BaseEvent` type, which provides common properties shared across all event types. ```typescript type BaseEvent = { type: EventType // Discriminator field timestamp?: number rawEvent?: any } ``` | Property | Type | Description | | ----------- | ------------------- | ----------------------------------------------------- | | `type` | `EventType` | The type of event (discriminator field for the union) | | `timestamp` | `number` (optional) | Timestamp when the event was created | | `rawEvent` | `any` (optional) | Original event data if this event was transformed | ## Lifecycle Events These events represent the lifecycle of an agent run. ### RunStartedEvent Signals the start of an agent run. ```typescript type RunStartedEvent = BaseEvent & { type: EventType.RUN_STARTED threadId: string runId: string } ``` | Property | Type | Description | | ---------- | -------- | ----------------------------- | | `threadId` | `string` | ID of the conversation thread | | `runId` | `string` | ID of the agent run | ### RunFinishedEvent Signals the successful completion of an agent run. ```typescript type RunFinishedEvent = BaseEvent & { type: EventType.RUN_FINISHED threadId: string runId: string } ``` | Property | Type | Description | | ---------- | -------- | ----------------------------- | | `threadId` | `string` | ID of the conversation thread | | `runId` | `string` | ID of the agent run | ### RunErrorEvent Signals an error during an agent run. ```typescript type RunErrorEvent = BaseEvent & { type: EventType.RUN_ERROR message: string code?: string } ``` | Property | Type | Description | | --------- | ------------------- | ------------- | | `message` | `string` | Error message | | `code` | `string` (optional) | Error code | ### StepStartedEvent Signals the start of a step within an agent run. ```typescript type StepStartedEvent = BaseEvent & { type: EventType.STEP_STARTED stepName: string } ``` | Property | Type | Description | | ---------- | -------- | ---------------- | | `stepName` | `string` | Name of the step | ### StepFinishedEvent Signals the completion of a step within an agent run. ```typescript type StepFinishedEvent = BaseEvent & { type: EventType.STEP_FINISHED stepName: string } ``` | Property | Type | Description | | ---------- | -------- | ---------------- | | `stepName` | `string` | Name of the step | ## Text Message Events These events represent the lifecycle of text messages in a conversation. ### TextMessageStartEvent Signals the start of a text message. ```typescript type TextMessageStartEvent = BaseEvent & { type: EventType.TEXT_MESSAGE_START messageId: string role: "assistant" } ``` | Property | Type | Description | | ----------- | ------------- | --------------------------------- | | `messageId` | `string` | Unique identifier for the message | | `role` | `"assistant"` | Role is always "assistant" | ### TextMessageContentEvent Represents a chunk of content in a streaming text message. ```typescript type TextMessageContentEvent = BaseEvent & { type: EventType.TEXT_MESSAGE_CONTENT messageId: string delta: string // Non-empty string } ``` | Property | Type | Description | | ----------- | -------- | ----------------------------------------- | | `messageId` | `string` | Matches the ID from TextMessageStartEvent | | `delta` | `string` | Text content chunk (non-empty) | ### TextMessageEndEvent Signals the end of a text message. ```typescript type TextMessageEndEvent = BaseEvent & { type: EventType.TEXT_MESSAGE_END messageId: string } ``` | Property | Type | Description | | ----------- | -------- | ----------------------------------------- | | `messageId` | `string` | Matches the ID from TextMessageStartEvent | ## Tool Call Events These events represent the lifecycle of tool calls made by agents. ### ToolCallStartEvent Signals the start of a tool call. ```typescript type ToolCallStartEvent = BaseEvent & { type: EventType.TOOL_CALL_START toolCallId: string toolCallName: string parentMessageId?: string } ``` | Property | Type | Description | | ----------------- | ------------------- | ----------------------------------- | | `toolCallId` | `string` | Unique identifier for the tool call | | `toolCallName` | `string` | Name of the tool being called | | `parentMessageId` | `string` (optional) | ID of the parent message | ### ToolCallArgsEvent Represents a chunk of argument data for a tool call. ```typescript type ToolCallArgsEvent = BaseEvent & { type: EventType.TOOL_CALL_ARGS toolCallId: string delta: string } ``` | Property | Type | Description | | ------------ | -------- | -------------------------------------- | | `toolCallId` | `string` | Matches the ID from ToolCallStartEvent | | `delta` | `string` | Argument data chunk | ### ToolCallEndEvent Signals the end of a tool call. ```typescript type ToolCallEndEvent = BaseEvent & { type: EventType.TOOL_CALL_END toolCallId: string } ``` | Property | Type | Description | | ------------ | -------- | -------------------------------------- | | `toolCallId` | `string` | Matches the ID from ToolCallStartEvent | ## State Management Events These events are used to manage agent state. ### StateSnapshotEvent Provides a complete snapshot of an agent's state. ```typescript type StateSnapshotEvent = BaseEvent & { type: EventType.STATE_SNAPSHOT snapshot: any // StateSchema } ``` | Property | Type | Description | | ---------- | ----- | ----------------------- | | `snapshot` | `any` | Complete state snapshot | ### StateDeltaEvent Provides a partial update to an agent's state using JSON Patch. ```typescript type StateDeltaEvent = BaseEvent & { type: EventType.STATE_DELTA delta: any[] // JSON Patch operations (RFC 6902) } ``` | Property | Type | Description | | -------- | ------- | ------------------------------ | | `delta` | `any[]` | Array of JSON Patch operations | ### MessagesSnapshotEvent Provides a snapshot of all messages in a conversation. ```typescript type MessagesSnapshotEvent = BaseEvent & { type: EventType.MESSAGES_SNAPSHOT messages: Message[] } ``` | Property | Type | Description | | ---------- | ----------- | ------------------------ | | `messages` | `Message[]` | Array of message objects | ## Special Events ### RawEvent Used to pass through events from external systems. ```typescript type RawEvent = BaseEvent & { type: EventType.RAW event: any source?: string } ``` | Property | Type | Description | | -------- | ------------------- | ------------------- | | `event` | `any` | Original event data | | `source` | `string` (optional) | Source of the event | ### CustomEvent Used for application-specific custom events. ```typescript type CustomEvent = BaseEvent & { type: EventType.CUSTOM name: string value: any } ``` | Property | Type | Description | | -------- | -------- | ------------------------------- | | `name` | `string` | Name of the custom event | | `value` | `any` | Value associated with the event | ## Event Schemas The SDK uses Zod schemas to validate events: ```typescript const EventSchemas = z.discriminatedUnion("type", [ TextMessageStartEventSchema, TextMessageContentEventSchema, TextMessageEndEventSchema, ToolCallStartEventSchema, ToolCallArgsEventSchema, ToolCallEndEventSchema, StateSnapshotEventSchema, StateDeltaEventSchema, MessagesSnapshotEventSchema, RawEventSchema, CustomEventSchema, RunStartedEventSchema, RunFinishedEventSchema, RunErrorEventSchema, StepStartedEventSchema, StepFinishedEventSchema, ]) ``` This allows for runtime validation of events and provides TypeScript type inference. # Overview Source: https://docs.agentwire.io/sdk/js/core/overview Core concepts in the Agent Wire Protocol SDK # @agentwire/core The Agent Wire Protocol SDK uses a streaming event-based architecture with strongly typed data structures. This package provides the foundation for connecting to agent systems. ```bash npm install @agentwire/core ``` ## Types Core data structures that represent the building blocks of the system: * [RunAgentInput](/sdk/js/core/types#runagentinput) - Input parameters for running agents * [Message](/sdk/js/core/types#message-types) - User assistant communication and tool usage * [Context](/sdk/js/core/types#context) - Contextual information provided to agents * [Tool](/sdk/js/core/types#tool) - Defines functions that agents can call * [State](/sdk/js/core/types#state) - Agent state management Complete documentation of all types in the @agentwire/core package ## Events Events that power communication between agents and frontends: * [Lifecycle Events](/sdk/js/core/events#lifecycle-events) - Run and step tracking * [Text Message Events](/sdk/js/core/events#text-message-events) - Assistant message streaming * [Tool Call Events](/sdk/js/core/events#tool-call-events) - Function call lifecycle * [State Management Events](/sdk/js/core/events#state-management-events) - Agent state updates * [Special Events](/sdk/js/core/events#special-events) - Raw and custom events Complete documentation of all events in the @agentwire/core package # Types Source: https://docs.agentwire.io/sdk/js/core/types Documentation for the core types used in the Agent Wire Protocol SDK # Core Types The Agent Wire Protocol SDK is built on a set of core types that represent the fundamental structures used throughout the system. This page documents these types and their properties. ## RunAgentInput Input parameters for running an agent. In the HTTP API, this is the body of the `POST` request. ```typescript type RunAgentInput = { threadId: string runId: string state: any messages: Message[] tools: Tool[] context: Context[] forwardedProps: any } ``` | Property | Type | Description | | ---------------- | ----------- | ---------------------------------------------- | | `threadId` | `string` | ID of the conversation thread | | `runId` | `string` | ID of the current run | | `state` | `any` | Current state of the agent | | `messages` | `Message[]` | Array of messages in the conversation | | `tools` | `Tool[]` | Array of tools available to the agent | | `context` | `Context[]` | Array of context objects provided to the agent | | `forwardedProps` | `any` | Additional properties forwarded to the agent | ## Message Types The SDK includes several message types that represent different kinds of messages in the system. ### Role Represents the possible roles a message sender can have. ```typescript type Role = "developer" | "system" | "assistant" | "user" | "tool" ``` ### DeveloperMessage Represents a message from a developer. ```typescript type DeveloperMessage = { id: string role: "developer" content: string name?: string } ``` | Property | Type | Description | | --------- | ------------- | ------------------------------------------------ | | `id` | `string` | Unique identifier for the message | | `role` | `"developer"` | Role of the message sender, fixed as "developer" | | `content` | `string` | Text content of the message (required) | | `name` | `string` | Optional name of the sender | ### SystemMessage Represents a system message. ```typescript type SystemMessage = { id: string role: "system" content: string name?: string } ``` | Property | Type | Description | | --------- | ---------- | --------------------------------------------- | | `id` | `string` | Unique identifier for the message | | `role` | `"system"` | Role of the message sender, fixed as "system" | | `content` | `string` | Text content of the message (required) | | `name` | `string` | Optional name of the sender | ### AssistantMessage Represents a message from an assistant. ```typescript type AssistantMessage = { id: string role: "assistant" content?: string name?: string toolCalls?: ToolCall[] } ``` | Property | Type | Description | | ----------- | ----------------------- | ------------------------------------------------ | | `id` | `string` | Unique identifier for the message | | `role` | `"assistant"` | Role of the message sender, fixed as "assistant" | | `content` | `string` (optional) | Text content of the message | | `name` | `string` (optional) | Name of the sender | | `toolCalls` | `ToolCall[]` (optional) | Tool calls made in this message | ### UserMessage Represents a message from a user. ```typescript type UserMessage = { id: string role: "user" content: string name?: string } ``` | Property | Type | Description | | --------- | -------- | ------------------------------------------- | | `id` | `string` | Unique identifier for the message | | `role` | `"user"` | Role of the message sender, fixed as "user" | | `content` | `string` | Text content of the message (required) | | `name` | `string` | Optional name of the sender | ### ToolMessage Represents a message from a tool. ```typescript type ToolMessage = { id: string content: string role: "tool" toolCallId: string } ``` | Property | Type | Description | | ------------ | -------- | -------------------------------------------- | | `id` | `string` | Unique identifier for the message | | `content` | `string` | Text content of the message | | `role` | `"tool"` | Role of the message sender, fixed as "tool" | | `toolCallId` | `string` | ID of the tool call this message responds to | ### Message A union type representing any type of message in the system. ```typescript type Message = | DeveloperMessage | SystemMessage | AssistantMessage | UserMessage | ToolMessage ``` ### ToolCall Represents a tool call made by an agent. ```typescript type ToolCall = { id: string type: "function" function: FunctionCall } ``` | Property | Type | Description | | ---------- | -------------- | ---------------------------------------- | | `id` | `string` | Unique identifier for the tool call | | `type` | `"function"` | Type of the tool call, always "function" | | `function` | `FunctionCall` | Details about the function being called | #### FunctionCall Represents function name and arguments in a tool call. ```typescript type FunctionCall = { name: string arguments: string } ``` | Property | Type | Description | | ----------- | -------- | ------------------------------------------------ | | `name` | `string` | Name of the function to call | | `arguments` | `string` | JSON-encoded string of arguments to the function | ## Context Represents a piece of contextual information provided to an agent. ```typescript type Context = { description: string value: string } ``` | Property | Type | Description | | ------------- | -------- | ------------------------------------------- | | `description` | `string` | Description of what this context represents | | `value` | `string` | The actual context value | ## Tool Defines a tool that can be called by an agent. ```typescript type Tool = { name: string description: string parameters: any // JSON Schema } ``` | Property | Type | Description | | ------------- | -------- | ------------------------------------------------ | | `name` | `string` | Name of the tool | | `description` | `string` | Description of what the tool does | | `parameters` | `any` | JSON Schema defining the parameters for the tool | ## State Represents the state of an agent during execution. ```typescript type State = any ``` The state type is flexible and can hold any data structure needed by the agent implementation. # @agentwire/encoder Source: https://docs.agentwire.io/sdk/js/encoder # @agentwire/proto Source: https://docs.agentwire.io/sdk/js/proto # Events Source: https://docs.agentwire.io/sdk/python/core/events Documentation for the events used in the Agent Wire Protocol Python SDK # Events The Agent Wire Protocol Python SDK uses a streaming event-based architecture. Events are the fundamental units of communication between agents and the frontend. This section documents the event types and their properties. ## EventType Enum `from agentwire.core import EventType` The `EventType` enum defines all possible event types in the system: ```python class EventType(str, Enum): TEXT_MESSAGE_START = "TEXT_MESSAGE_START" TEXT_MESSAGE_CONTENT = "TEXT_MESSAGE_CONTENT" TEXT_MESSAGE_END = "TEXT_MESSAGE_END" TOOL_CALL_START = "TOOL_CALL_START" TOOL_CALL_ARGS = "TOOL_CALL_ARGS" TOOL_CALL_END = "TOOL_CALL_END" STATE_SNAPSHOT = "STATE_SNAPSHOT" STATE_DELTA = "STATE_DELTA" MESSAGES_SNAPSHOT = "MESSAGES_SNAPSHOT" RAW = "RAW" CUSTOM = "CUSTOM" RUN_STARTED = "RUN_STARTED" RUN_FINISHED = "RUN_FINISHED" RUN_ERROR = "RUN_ERROR" STEP_STARTED = "STEP_STARTED" STEP_FINISHED = "STEP_FINISHED" ``` ## BaseEvent `from agentwire.core import BaseEvent` All events inherit from the `BaseEvent` class, which provides common properties shared across all event types. ```python class BaseEvent(ConfiguredBaseModel): type: EventType timestamp: Optional[int] = None raw_event: Optional[Any] = None ``` | Property | Type | Description | | ----------- | --------------- | ----------------------------------------------------- | | `type` | `EventType` | The type of event (discriminator field for the union) | | `timestamp` | `Optional[int]` | Timestamp when the event was created | | `raw_event` | `Optional[Any]` | Original event data if this event was transformed | ## Lifecycle Events These events represent the lifecycle of an agent run. ### RunStartedEvent `from agentwire.core import RunStartedEvent` Signals the start of an agent run. ```python class RunStartedEvent(BaseEvent): type: Literal[EventType.RUN_STARTED] thread_id: str run_id: str ``` | Property | Type | Description | | ----------- | ----- | ----------------------------- | | `thread_id` | `str` | ID of the conversation thread | | `run_id` | `str` | ID of the agent run | ### RunFinishedEvent `from agentwire.core import RunFinishedEvent` Signals the successful completion of an agent run. ```python class RunFinishedEvent(BaseEvent): type: Literal[EventType.RUN_FINISHED] thread_id: str run_id: str ``` | Property | Type | Description | | ----------- | ----- | ----------------------------- | | `thread_id` | `str` | ID of the conversation thread | | `run_id` | `str` | ID of the agent run | ### RunErrorEvent `from agentwire.core import RunErrorEvent` Signals an error during an agent run. ```python class RunErrorEvent(BaseEvent): type: Literal[EventType.RUN_ERROR] message: str code: Optional[str] = None ``` | Property | Type | Description | | --------- | --------------- | ------------- | | `message` | `str` | Error message | | `code` | `Optional[str]` | Error code | ### StepStartedEvent `from agentwire.core import StepStartedEvent` Signals the start of a step within an agent run. ```python class StepStartedEvent(BaseEvent): type: Literal[EventType.STEP_STARTED] step_name: str ``` | Property | Type | Description | | ----------- | ----- | ---------------- | | `step_name` | `str` | Name of the step | ### StepFinishedEvent `from agentwire.core import StepFinishedEvent` Signals the completion of a step within an agent run. ```python class StepFinishedEvent(BaseEvent): type: Literal[EventType.STEP_FINISHED] step_name: str ``` | Property | Type | Description | | ----------- | ----- | ---------------- | | `step_name` | `str` | Name of the step | ## Text Message Events These events represent the lifecycle of text messages in a conversation. ### TextMessageStartEvent `from agentwire.core import TextMessageStartEvent` Signals the start of a text message. ```python class TextMessageStartEvent(BaseEvent): type: Literal[EventType.TEXT_MESSAGE_START] message_id: str role: Literal["assistant"] ``` | Property | Type | Description | | ------------ | ---------------------- | --------------------------------- | | `message_id` | `str` | Unique identifier for the message | | `role` | `Literal["assistant"]` | Role is always "assistant" | ### TextMessageContentEvent `from agentwire.core import TextMessageContentEvent` Represents a chunk of content in a streaming text message. ```python class TextMessageContentEvent(BaseEvent): type: Literal[EventType.TEXT_MESSAGE_CONTENT] message_id: str delta: str # Non-empty string def model_post_init(self, __context): if len(self.delta) == 0: raise ValueError("Delta must not be an empty string") ``` | Property | Type | Description | | ------------ | ----- | ----------------------------------------- | | `message_id` | `str` | Matches the ID from TextMessageStartEvent | | `delta` | `str` | Text content chunk (non-empty) | ### TextMessageEndEvent `from agentwire.core import TextMessageEndEvent` Signals the end of a text message. ```python class TextMessageEndEvent(BaseEvent): type: Literal[EventType.TEXT_MESSAGE_END] message_id: str ``` | Property | Type | Description | | ------------ | ----- | ----------------------------------------- | | `message_id` | `str` | Matches the ID from TextMessageStartEvent | ## Tool Call Events These events represent the lifecycle of tool calls made by agents. ### ToolCallStartEvent `from agentwire.core import ToolCallStartEvent` Signals the start of a tool call. ```python class ToolCallStartEvent(BaseEvent): type: Literal[EventType.TOOL_CALL_START] tool_call_id: str tool_call_name: str parent_message_id: Optional[str] = None ``` | Property | Type | Description | | ------------------- | --------------- | ----------------------------------- | | `tool_call_id` | `str` | Unique identifier for the tool call | | `tool_call_name` | `str` | Name of the tool being called | | `parent_message_id` | `Optional[str]` | ID of the parent message | ### ToolCallArgsEvent `from agentwire.core import ToolCallArgsEvent` Represents a chunk of argument data for a tool call. ```python class ToolCallArgsEvent(BaseEvent): type: Literal[EventType.TOOL_CALL_ARGS] tool_call_id: str delta: str ``` | Property | Type | Description | | -------------- | ----- | -------------------------------------- | | `tool_call_id` | `str` | Matches the ID from ToolCallStartEvent | | `delta` | `str` | Argument data chunk | ### ToolCallEndEvent `from agentwire.core import ToolCallEndEvent` Signals the end of a tool call. ```python class ToolCallEndEvent(BaseEvent): type: Literal[EventType.TOOL_CALL_END] tool_call_id: str ``` | Property | Type | Description | | -------------- | ----- | -------------------------------------- | | `tool_call_id` | `str` | Matches the ID from ToolCallStartEvent | ## State Management Events These events are used to manage agent state. ### StateSnapshotEvent `from agentwire.core import StateSnapshotEvent` Provides a complete snapshot of an agent's state. ```python class StateSnapshotEvent(BaseEvent): type: Literal[EventType.STATE_SNAPSHOT] snapshot: State ``` | Property | Type | Description | | ---------- | ------- | ----------------------- | | `snapshot` | `State` | Complete state snapshot | ### StateDeltaEvent `from agentwire.core import StateDeltaEvent` Provides a partial update to an agent's state using JSON Patch. ```python class StateDeltaEvent(BaseEvent): type: Literal[EventType.STATE_DELTA] delta: List[Any] # JSON Patch (RFC 6902) ``` | Property | Type | Description | | -------- | ----------- | ------------------------------ | | `delta` | `List[Any]` | Array of JSON Patch operations | ### MessagesSnapshotEvent `from agentwire.core import MessagesSnapshotEvent` Provides a snapshot of all messages in a conversation. ```python class MessagesSnapshotEvent(BaseEvent): type: Literal[EventType.MESSAGES_SNAPSHOT] messages: List[Message] ``` | Property | Type | Description | | ---------- | --------------- | ------------------------ | | `messages` | `List[Message]` | Array of message objects | ## Special Events ### RawEvent `from agentwire.core import RawEvent` Used to pass through events from external systems. ```python class RawEvent(BaseEvent): type: Literal[EventType.RAW] event: Any source: Optional[str] = None ``` | Property | Type | Description | | -------- | --------------- | ------------------- | | `event` | `Any` | Original event data | | `source` | `Optional[str]` | Source of the event | ### CustomEvent `from agentwire.core import CustomEvent` Used for application-specific custom events. ```python class CustomEvent(BaseEvent): type: Literal[EventType.CUSTOM] name: str value: Any ``` | Property | Type | Description | | -------- | ----- | ------------------------------- | | `name` | `str` | Name of the custom event | | `value` | `Any` | Value associated with the event | ## Event Discrimination `from agentwire.core import Event` The SDK uses Pydantic's discriminated unions for event validation: ```python Event = Annotated[ Union[ TextMessageStartEvent, TextMessageContentEvent, TextMessageEndEvent, ToolCallStartEvent, ToolCallArgsEvent, ToolCallEndEvent, StateSnapshotEvent, StateDeltaEvent, MessagesSnapshotEvent, RawEvent, CustomEvent, RunStartedEvent, RunFinishedEvent, RunErrorEvent, StepStartedEvent, StepFinishedEvent, ], Field(discriminator="type") ] ``` This allows for runtime validation of events and type checking at development time. # Overview Source: https://docs.agentwire.io/sdk/python/core/overview Core concepts in the Agent Wire Protocol SDK # agentwire.core The Agent Wire Protocol SDK uses a streaming event-based architecture with strongly typed data structures. This package provides the foundation for connecting to agent systems. ```python from agentwire.core import ... ``` ## Types Core data structures that represent the building blocks of the system: * [RunAgentInput](/sdk/python/core/types#runagentinput) - Input parameters for running agents * [Message](/sdk/python/core/types#message-types) - User assistant communication and tool usage * [Context](/sdk/python/core/types#context) - Contextual information provided to agents * [Tool](/sdk/python/core/types#tool) - Defines functions that agents can call * [State](/sdk/python/core/types#state) - Agent state management Complete documentation of all types in the agentwire.core package ## Events Events that power communication between agents and frontends: * [Lifecycle Events](/sdk/python/core/events#lifecycle-events) - Run and step tracking * [Text Message Events](/sdk/python/core/events#text-message-events) - Assistant message streaming * [Tool Call Events](/sdk/python/core/events#tool-call-events) - Function call lifecycle * [State Management Events](/sdk/python/core/events#state-management-events) - Agent state updates * [Special Events](/sdk/python/core/events#special-events) - Raw and custom events Complete documentation of all events in the agentwire.core package # Types Source: https://docs.agentwire.io/sdk/python/core/types Documentation for the core types used in the Agent Wire Protocol Python SDK # Core Types The Agent Wire Protocol Python SDK is built on a set of core types that represent the fundamental structures used throughout the system. This page documents these types and their properties. ## RunAgentInput `from agentwire.core import RunAgentInput` Input parameters for running an agent. In the HTTP API, this is the body of the `POST` request. ```python class RunAgentInput(ConfiguredBaseModel): thread_id: str run_id: str state: Any messages: List[Message] tools: List[Tool] context: List[Context] forwarded_props: Any ``` | Property | Type | Description | | ----------------- | --------------- | --------------------------------------------- | | `thread_id` | `str` | ID of the conversation thread | | `run_id` | `str` | ID of the current run | | `state` | `Any` | Current state of the agent | | `messages` | `List[Message]` | List of messages in the conversation | | `tools` | `List[Tool]` | List of tools available to the agent | | `context` | `List[Context]` | List of context objects provided to the agent | | `forwarded_props` | `Any` | Additional properties forwarded to the agent | ## Message Types The SDK includes several message types that represent different kinds of messages in the system. ### Role `from agentwire.core import Role` Represents the possible roles a message sender can have. ```python Role = Literal["developer", "system", "assistant", "user", "tool"] ``` ### DeveloperMessage `from agentwire.core import DeveloperMessage` Represents a message from a developer. ```python class DeveloperMessage(BaseMessage): role: Literal["developer"] content: str ``` | Property | Type | Description | | --------- | ---------------------- | ------------------------------------------------ | | `id` | `str` | Unique identifier for the message | | `role` | `Literal["developer"]` | Role of the message sender, fixed as "developer" | | `content` | `str` | Text content of the message (required) | | `name` | `Optional[str]` | Optional name of the sender | ### SystemMessage `from agentwire.core import SystemMessage` Represents a system message. ```python class SystemMessage(BaseMessage): role: Literal["system"] content: str ``` | Property | Type | Description | | --------- | ------------------- | --------------------------------------------- | | `id` | `str` | Unique identifier for the message | | `role` | `Literal["system"]` | Role of the message sender, fixed as "system" | | `content` | `str` | Text content of the message (required) | | `name` | `Optional[str]` | Optional name of the sender | ### AssistantMessage `from agentwire.core import AssistantMessage` Represents a message from an assistant. ```python class AssistantMessage(BaseMessage): role: Literal["assistant"] content: Optional[str] = None tool_calls: Optional[List[ToolCall]] = None ``` | Property | Type | Description | | ------------ | -------------------------- | ------------------------------------------------ | | `id` | `str` | Unique identifier for the message | | `role` | `Literal["assistant"]` | Role of the message sender, fixed as "assistant" | | `content` | `Optional[str]` | Text content of the message | | `name` | `Optional[str]` | Name of the sender | | `tool_calls` | `Optional[List[ToolCall]]` | Tool calls made in this message | ### UserMessage `from agentwire.core import UserMessage` Represents a message from a user. ```python class UserMessage(BaseMessage): role: Literal["user"] content: str ``` | Property | Type | Description | | --------- | ----------------- | ------------------------------------------- | | `id` | `str` | Unique identifier for the message | | `role` | `Literal["user"]` | Role of the message sender, fixed as "user" | | `content` | `str` | Text content of the message (required) | | `name` | `Optional[str]` | Optional name of the sender | ### ToolMessage `from agentwire.core import ToolMessage` Represents a message from a tool. ```python class ToolMessage(ConfiguredBaseModel): id: str role: Literal["tool"] content: str tool_call_id: str ``` | Property | Type | Description | | -------------- | ----------------- | -------------------------------------------- | | `id` | `str` | Unique identifier for the message | | `content` | `str` | Text content of the message | | `role` | `Literal["tool"]` | Role of the message sender, fixed as "tool" | | `tool_call_id` | `str` | ID of the tool call this message responds to | ### Message `from agentwire.core import Message` A union type representing any type of message in the system. ```python Message = Annotated[ Union[DeveloperMessage, SystemMessage, AssistantMessage, UserMessage, ToolMessage], Field(discriminator="role") ] ``` ### ToolCall `from agentwire.core import ToolCall` Represents a tool call made by an agent. ```python class ToolCall(ConfiguredBaseModel): id: str type: Literal["function"] function: FunctionCall ``` | Property | Type | Description | | ---------- | --------------------- | ---------------------------------------- | | `id` | `str` | Unique identifier for the tool call | | `type` | `Literal["function"]` | Type of the tool call, always "function" | | `function` | `FunctionCall` | Details about the function being called | #### FunctionCall `from agentwire.core import FunctionCall` Represents function name and arguments in a tool call. ```python class FunctionCall(ConfiguredBaseModel): name: str arguments: str ``` | Property | Type | Description | | ----------- | ----- | ------------------------------------------------ | | `name` | `str` | Name of the function to call | | `arguments` | `str` | JSON-encoded string of arguments to the function | ## Context `from agentwire.core import Context` Represents a piece of contextual information provided to an agent. ```python class Context(ConfiguredBaseModel): description: str value: str ``` | Property | Type | Description | | ------------- | ----- | ------------------------------------------- | | `description` | `str` | Description of what this context represents | | `value` | `str` | The actual context value | ## Tool `from agentwire.core import Tool` Defines a tool that can be called by an agent. ```python class Tool(ConfiguredBaseModel): name: str description: str parameters: Any # JSON Schema ``` | Property | Type | Description | | ------------- | ----- | ------------------------------------------------ | | `name` | `str` | Name of the tool | | `description` | `str` | Description of what the tool does | | `parameters` | `Any` | JSON Schema defining the parameters for the tool | ## State `from agentwire.core import State` Represents the state of an agent during execution. ```python State = Any ``` The state type is flexible and can hold any data structure needed by the agent implementation. # Overview Source: https://docs.agentwire.io/sdk/python/encoder/overview Documentation for encoding Agent Wire Protocol events # Event Encoder The Agent Wire Protocol uses a streaming approach to send events from agents to clients. The `EventEncoder` class provides the functionality to encode events into a format that can be sent over HTTP. ## EventEncoder `from agentwire.encoder import EventEncoder` The `EventEncoder` class is responsible for encoding `BaseEvent` objects into string representations that can be transmitted to clients. ```python from agentwire.core import BaseEvent from agentwire.encoder import EventEncoder # Initialize the encoder encoder = EventEncoder() # Encode an event encoded_event = encoder.encode(event) ``` ### Usage The `EventEncoder` is typically used in HTTP handlers to convert event objects into a stream of data. The current implementation encodes events as Server-Sent Events (SSE), which can be consumed by clients using the EventSource API. ### Methods #### `__init__(accept: str = None)` Creates a new encoder instance. | Parameter | Type | Description | | --------- | ---------------- | ----------------------------------- | | `accept` | `str` (optional) | Content type accepted by the client | #### `encode(event: BaseEvent) -> str` Encodes an event into a string representation. | Parameter | Type | Description | | --------- | ----------- | ------------------- | | `event` | `BaseEvent` | The event to encode | **Returns**: A string representation of the event in SSE format. ### Example ```python from agentwire.core import TextMessageContentEvent, EventType from agentwire.encoder import EventEncoder # Create an event event = TextMessageContentEvent( type=EventType.TEXT_MESSAGE_CONTENT, message_id="msg_123", delta="Hello, world!" ) # Initialize the encoder encoder = EventEncoder() # Encode the event encoded_event = encoder.encode(event) print(encoded_event) # Output: data: {"type":"TEXT_MESSAGE_CONTENT","messageId":"msg_123","delta":"Hello, world!"}\n\n ``` ### Implementation Details Internally, the encoder converts events to JSON and formats them as Server-Sent Events with the following structure: ``` data: {json-serialized event}\n\n ``` This format allows clients to receive a continuous stream of events and process them as they arrive. # Developing with Cursor Source: https://docs.agentwire.io/tutorials/cursor Use Cursor to build AWP implementations faster This guide will help you set up Cursor to help you build custom Agent Wire Protocol (AWP) servers and clients faster. The same principles apply to other IDE's like Windsurf, VSCode, etc. ## Adding the documentation to Cursor 1. Open up the Cursor settings 2. Go to Features > Docs and click "+ Add new Doc" 3. Paste in the following URL: [https://docs.agentwire.io/llms-full.txt](https://docs.agentwire.io/llms-full.txt) 4. Click "Add" ## Using the documentation Now you can use the documentation to help you build your AWP project. Load the docs into the current prompt by typing the `@` symbol, selecting "Docs" and then selecting "Agent Wire Protocol" from the list. Happy coding! ## Best practices When building AWP servers with Cursor: * Break down complex problems into smaller steps * Have a look at what the agent was doing by checking which files it edited (above the chat input) * Let the agent write unit tests to verify your implementation * Follow AWP protocol specifications carefully # Debugging Source: https://docs.agentwire.io/tutorials/debugging A comprehensive guide to debugging Agent Wire Protocol (AWP) integrations TODO