Picsha AI

Picsha AI A2A Agent

Overview

The Picsha AI API supports the Agent-to-Agent (A2A) protocol, an open standard designed to facilitate communication, collaboration, and task delegation between autonomous AI agents.

While the Model Context Protocol (MCP) connects a single agent directly to data and tools, A2A operates at a higher orchestration layer, enabling disparate agents—built on different frameworks and technologies—to discover Picsha, request information, and delegate tasks using natural language.

By exposing an A2A-compliant interface, your agents can coordinate with Picsha as a team member, asking it to locate assets, update metadata, organize collections, or generate CDN rendering links.


Connection Details

The A2A agent interface is served directly alongside your Picsha AI API server:

  • Agent Card (Discovery): https://api.picsha.ai/v1/a2a/card (or https://api.picsha.ai/v1/a2a/)
  • JSON-RPC Endpoint: https://api.picsha.ai/v1/a2a/jsonrpc
  • Protocol Version: 0.3.0

Authentication

Authentication works identically to the core Picsha AI API. You must include your Picsha API key as a Bearer token in the request headers:

POST /v1/a2a/jsonrpc HTTP/1.1
Host: api.picsha.ai
Authorization: Bearer <YOUR_PICSHA_API_KEY>
Content-Type: application/json

Capabilities & Skills

The Picsha A2A Agent exposes a single high-level skill, manage_assets, which represents its complete set of Digital Asset Management (DAM) operations. Under the hood, the agent runs an autonomous reasoning loop powered by AWS Bedrock (Anthropic Claude) to determine how to execute client requests using the platform's internal tools.

Supported Platform Tools

[!NOTE] A2A vs MCP Toolsets The A2A tool list below focuses exclusively on headless orchestration and background tasks. Tools present in the MCP specification that are purely for human-in-the-loop chat UIs (like render_asset_preview, poll_render, and escalate_to_support) are intentionally omitted from A2A. Furthermore, heavy asynchronous tools like reanalyze_asset and get_job_status are excluded because A2A agents rely on native Webhooks rather than blocking polling loops for long-running workflows.

When a peer agent delegates a task via A2A, the Picsha Agent Executor can orchestrate calls to:

  1. search_assets(query, mode): Standard or hybrid semantic vector search.
  2. get_asset(id): Detailed asset metadata retrieval.
  3. list_recent_assets(limit): Retrieve recently added files.
  4. update_asset(id, tags, metadata): Update tags or custom fields.
  5. delete_asset(id, force?): Soft-deletes the asset (moves to Trash). Pass force: true for permanent deletion (requires Admin Key).
  6. moderate_asset(id, action): Approve or reject an asset (sets status to completed or rejected).
  7. create_dam_group(name, description, assetIds): Organize files into folders/collections.
  8. link_assets(sourceId, targetId, relationshipType): Relate variations or parent/child assets.
  9. trigger_url_ingest(url, filename, config): Import files from public URLs.
  10. get_presigned_upload_url(filename, contentType): Direct-to-S3 secure uploads.
  11. generate_render_url(id, transformations): Retrieve transformed WebP images on the fly.

Integrating with A2A Clients

To interact with the Picsha A2A agent from your own TypeScript application, install the official SDK:

npm install @a2a-js/sdk

TypeScript Client Example

The following example demonstrates how to discover the Picsha A2A Agent using its Card, establish a client connection, and delegate a task to search for media assets:

import { A2AClient } from "@a2a-js/sdk/client";
import { Message } from "@a2a-js/sdk";
import { randomUUID } from "crypto";

async function run() {
    // 1. Establish the A2A client pointing to the Picsha JSON-RPC endpoint
    const client = new A2AClient({
        url: "https://api.picsha.ai/v1/a2a/jsonrpc",
        headers: {
            "Authorization": `Bearer ${process.env.PICSHA_API_KEY}`
        }
    });

    console.log("Sending task to Picsha Agent...");
    
    // 2. Delegate a task using the standard message/send method
    const response = await client.sendMessage({
        message: {
            kind: "message",
            messageId: randomUUID(),
            role: "user",
            parts: [{
                kind: "text",
                text: "Find the 3 most recent pictures of dogs in the collection"
            }]
        }
    });

    if (response.kind === "message") {
        const textResponse = response.parts
            .map(part => part.text)
            .join("\n");
        console.log("Picsha Response:\n", textResponse);
    } else {
        // Returned a Task indicating a long-running execution
        console.log(`Task initiated with ID: ${response.id}. Status: ${response.status}`);
    }
}

run().catch(console.error);