--- title: Getting Started description: SDK overview and key workflows for building custom agent interfaces --- The Kagenti ADK TypeScript Client SDK simplifies building custom UIs for A2A agents. It handles agent service demands, maps task status updates to UI actions, and provides a typed platform API client. Use it to fulfill agent requirements, render interactive elements like forms and approvals, and manage communication between your UI and Kagenti ADK. It builds on the [Agent2Agent Protocol (A2A)](https://a2a-protocol.org/) and provides two layers: 1. A2A extensions and helpers that translate agent card demands such as LLM access, embeddings, OAuth, and secrets into client fulfillments like API keys, model choices, redirect URIs, and secret values, plus UI metadata. 2. A platform API client that talks to the Kagenti ADK server. The SDK also exports A2A protocol types and Zod schemas so your UI can stay in sync with the protocol. ## Quick Start ### 1. Install ```bash npm i @kagenti/adk @a2a-js/sdk ``` ### 2. Create the platform API client ```typescript import { buildApiClient, createAuthenticatedFetch } from "@kagenti/adk"; const baseUrl = "https://your-adk-instance.com"; const api = buildApiClient({ baseUrl, fetch: createAuthenticatedFetch(accessToken), }); ``` `buildApiClient` exposes the platform API with typed responses and runtime validation. Use the user access token from your identity provider (OIDC/OAuth) for UI side API calls. **Browser clients require CORS** If your custom UI runs on a different origin than your Kagenti ADK server, enable CORS on the server for your frontend origin. See **[Cross-Origin Resource Sharing Configuration](../deploy-adk/deployment-guide#cross-origin-resource-sharing-configuration)**. If allowing origins directly is not possible, route calls through a same-origin frontend proxy. ### 3. Create context and context token ```typescript const providers = unwrapResult(await api.listProviders()); const providerId = providers[0]?.id; const context = unwrapResult( await api.createContext({ provider_id: providerId }), ); const contextToken = unwrapResult( await api.createContextToken({ context_id: context.id, grant_global_permissions: { llm: ["*"], embeddings: ["*"], a2a_proxy: ["*"], }, grant_context_permissions: { files: ["*"], vector_stores: ["*"], context_data: ["*"], }, }), ); ``` **Finding `providerId`** Use `listProviders` or `readProviderByLocation` from the platform API to identify the agent you want. See **[Platform API Client](./platform-api-client)** for the provider endpoints. Context tokens are scoped for agent use and can also authenticate to the platform API when running inside the agent. See **[Permissions and Tokens](./permissions-and-tokens)** for token types and scopes. **Token usage summary** - Use **access token** for platform API calls from the UI. - Use **context token** for A2A client calls and agent card fetches. All API calls return `ApiResult`. Use `unwrapResult` if you want exceptions, and then handle errors with `isHttpError`, `isNetworkError`, `isParseError`, and `isValidationError`. ### 4. Create an A2A client and send a message Pass the **context token** to the A2A client fetch. Then fetch the agent card, resolve demands, and stream a message. For a full walkthrough (status updates, user responses, and cancellation), see **[A2A Client Integration](./a2a-client)**. ```typescript import { ClientFactory, ClientFactoryOptions, DefaultAgentCardResolver, JsonRpcTransportFactory, } from "@a2a-js/sdk/client"; import { createAuthenticatedFetch, getAgentCardPath } from "@kagenti/adk"; const fetchImpl = createAuthenticatedFetch(contextToken.token); const factory = new ClientFactory( ClientFactoryOptions.createFrom(ClientFactoryOptions.default, { transports: [new JsonRpcTransportFactory({ fetchImpl })], cardResolver: new DefaultAgentCardResolver({ fetchImpl }), }), ); const agentCardPath = getAgentCardPath(providerId); const client = await factory.createFromUrl(baseUrl, agentCardPath); const stream = client.sendMessageStream({ message: { kind: "message", role: "user", messageId: crypto.randomUUID(), contextId: context.id, parts: [{ kind: "text", text: "Hello" }], }, }); ``` `createAuthenticatedFetch` attaches the `Authorization` header to every request so the A2A client can load the agent card and open JSON RPC streams with authentication. The agent card URL follows this convention: `{baseUrl}/api/v1/a2a/{providerId}/.well-known/agent-card.json` - `baseUrl` is your Kagenti ADK server root - `providerId` is the agent provider identifier `getAgentCardPath(providerId)` returns the **path portion** of that URL. Use it with `ClientFactory.createFromUrl(baseUrl, agentCardPath)` so the client can resolve the full agent card endpoint. **Need UI events and follow up messages?** The **[A2A Client Integration](./a2a-client)** shows how to handle status updates, render forms and approvals, and respond with user metadata. ## Architecture overview ```mermaid graph TB subgraph CustomUI [Custom UI Application] SDK[Kagenti ADK] A2AClient[A2A Client] end subgraph Kagenti ADK [Kagenti ADK Platform] Agent[Agent] API[Platform API] end SDK -->|"handleAgentCard
resolveMetadata"| A2AClient A2AClient -->|"A2A Protocol Messages"| Agent Agent -->|"Task Status Updates"| A2AClient A2AClient -->|"handleTaskStatusUpdate"| SDK SDK -->|"buildApiClient"| API style SDK fill:#e1f5ff,color:#000 style A2AClient fill:#fff4e1,color:#000 style Agent fill:#e8f5e9,color:#000 style API fill:#f3e5f5,color:#000 ``` ## SDK entrypoints The SDK is split into focused entrypoints: 1. `@kagenti/adk` for everything 2. `@kagenti/adk/api` for platform API client, schemas, and types 3. `@kagenti/adk/core` for extension helpers and A2A interaction utilities 4. `@kagenti/adk/extensions` for A2A extension definitions and types ## Protocol Types and Schemas The SDK exports A2A protocol types and Zod schemas that match the Kagenti ADK UI usage, including: - `Message`, `Part`, and `Task` types - `TaskStatusUpdateEvent` and `TaskArtifactUpdateEvent` - UI and service extension schemas These exports are useful when building strongly typed UI layers or validating inbound messages. ## Next Steps - **[Custom UI Architecture Guide](./architecture-guide)** for a practical implementation approach using the `chat-ui` reference example - **[A2A Client Integration](./a2a-client)** for the full streaming, UI events, and response flow - **[Agent Requirements](./agent-requirements)** for service and UI extension handling - **[Agent Responses](./agent-responses)** for rendering message parts and citations - **[User Messages](./user-messages)** for composing user messages with metadata - **[Error Handling](./error-handling)** for platform and extension error patterns - **[Platform API Client](./platform-api-client)** for endpoint reference and error helpers