Skip to content

Project Management

AgentScope-Studio provides powerful project management capabilities to help you visually manage your AgentScope projects. Through the organizational structure of Projects and Runs, you can clearly separate and manage your observability data.

Concepts

In AgentScope-Studio, a Project contains multiple Runs. Specifically:

  • Projects: Used to organize and isolate different AI applications or experiments
  • Runs: Individual execution instances within a project, similar to sessions, tracking a complete running process

Project Management

The Projects page in AgentScope-Studio provides an overview and management functionality for running projects:

Project Management

Click on any project in the project list to enter the run management interface and view all run instances under that project.

Run Instance Management

Run Visualization

Run instances contain complete execution tracking and status monitoring functionality. In the (left) sidebar, all run instances under the project are stacked in chronological order. Click on any run instance to view its complete interaction history and status in a Chatbot-style UI. In addition, the right panel provides detailed information and statistics for that run.

Run Management

In AgentScope, a single agent reply (i.e., calling the reply function once) generates multiple messages (Msg objects). These messages may be prompt messages to guide the LLM (with role "user"), or tool execution results (with role "system").

Therefore, at the visualization level, we introduce the concept of reply above the message level to organize multiple messages together into a complete agent reply unit. In the run visualization interface, developers can choose to view messages by replyId or msg.id.

User Input Hosting

When an AgentScope project connects to Studio, Studio automatically hosts user input and pushes it in real-time to the Python agent application via WebSocket. Studio also supports multiple different UserAgent instances within a single run instance, enabling multi-user collaborative interaction scenarios.

Run Trace Visualization

AgentScope-Studio also provides OpenTelemetry-based trace data visualization in the right panel, helping developers understand detailed inputs and outputs of agent objects, LLM calls, tool usage, and other components during each run.

API Protocol

The API protocols related to project management in AgentScope-Studio are as follows:

Note: For detailed information about Trace data format, push mechanism, and integration examples, please refer to the Trace documentation.

FunctionEndpointMethodPurpose
Register Run/trpc/registerRunPOSTRegister a new Agent run instance
Push Message/trpc/pushMessagePOSTSend Agent messages to the Web interface
Request User Input/trpc/requestUserInputPOSTAgent actively requests user input

1. Register Run Protocol

Register a run instance on Studio.

FieldTypeRequiredDescription
idstringRun instance ID
projectstringProject name
namestringRun instance name
timestampstringISO timestamp
pidnumberProcess ID
statusenumRun status (e.g., "running", "finished", "error")

2. Message Push Protocol

Send Msg objects to Studio for display.

FieldTypeRequiredDescription
runIdstringRun instance ID
replyIdstringReply message ID
replyNamestringName of the replier
replyRolestringRole of the replier (e.g., "assistant", "user")
msg.idstringMessage ID
msg.namestringMessage sender name
msg.rolestringMessage sender role (e.g., "assistant", "user", "system")
msg.contentContentBlocksMessage content
msg.metadataobjectMessage metadata
msg.timestampstringMessage ISO timestamp

ContentBlocks Format:

ContentBlocks is an array of content blocks. Each block has a type field that determines its structure. Supported content block types include:

  • Text Block (type: "text"): Contains a text field storing message content
  • Thinking Block (type: "thinking"): Contains a thinking field storing reasoning content
  • Image Block (type: "image"): Contains a source field, can be base64 data or URL
  • Audio Block (type: "audio"): Contains a source field, can be base64 data or URL
  • Video Block (type: "video"): Contains a source field, can be base64 data or URL
  • Tool Use Block (type: "tool_use"): Contains id, name, and input fields
  • Tool Result Block (type: "tool_result"): Contains id, name, and output fields

For media blocks (image, audio, video), source can be:

  • Base64 Source: { type: "base64", media_type: string, data: string }
  • URL Source: { type: "url", url: string }

Example:

python
content_blocks = [
    {
        "type": "text",
        "text": "Greetings from your agent!"
    },
    {
        "type": "image",
        "source": {
            "type": "base64",
            "media_type": "image/jpeg",
            "data": "data:image/jpeg;base64,/9j/4AAQSkZJRg..."
        }
    },
    {
        "type": "tool_use",
        "id": "tool-123",
        "name": "search",
        "input": {"query": "weather"}
    }
]

3. User Input Protocol

Request user input on the Studio frontend page with a specific role/name/identity.

Request Fields:

FieldTypeRequiredDescription
requestIdstringUser input request ID
runIdstringRun instance ID
agentIdstringAgent ID
agentNamestringAgent name
structuredInputobjectJSON Schema for structured input form

The specific implementation logic for user input involves multi-party interaction between the Python application, Studio server, and frontend. Below is the detailed interaction flow:

User Input Flow

  1. Agent Sends Request: The Agent sends a user input request to the Studio server via POST request
  2. Server Saves Request: The Studio server saves the request to the database and pushes it to the Web client via WebSocket
  3. User Input: The user enters content in the Web interface
  4. Client Sends: The Web client sends the user input back to the server via WebSocket
  5. Server Forwards: The server validates and forwards the user input to the Agent's WebSocket connection
  6. Agent Receives: The Agent receives the user input via WebSocket and continues execution

Integration Example

The following example demonstrates how to integrate project management-related protocols:

python
from agentscope.message import Msg
from datetime import datetime
from queue import Queue
from threading import Event
from typing import Any, List

import requests
import shortuuid
import socketio


class StudioClient:
    """Complete Studio client for custom Agent integration"""

    def __init__(self, studio_url: str):
        self.studio_url = studio_url
        self.sio = socketio.Client()
        self.input_queues = {}
        self.input_events = {}

    def register_run(
        self,
        id: str,
        project: str,
        name: str,
        timestamp: str,
        pid: int,
        status: str,
    ) -> None:
        """Register a run instance"""
        response = requests.post(
            f"{self.studio_url}/trpc/registerRun",
            json={
                "id": id,
                "project": project,
                "name": name,
                "timestamp": timestamp,
                "pid": pid,
                "status": status,
            },
            timeout=10
        )
        response.raise_for_status()

        # Connect WebSocket to receive user input
        self.sio.connect(
            self.studio_url,
            namespaces=["/python"],
            auth={"run_id": id}
        )

        # Listen for user input
        @self.sio.on("forwardUserInput", namespace="/python")
        def receive_user_input(
                request_id: str,
                blocks_input: List[dict],
                structured_input: dict[str, Any],
        ) -> None:
            if request_id in self.input_queues:
                self.input_queues[request_id].put({
                    "blocks_input": blocks_input,
                    "structured_input": structured_input,
                })
                self.input_events[request_id].set()

    def push_message(
        self,
        run_id: str,
        reply_id: str,
        reply_name: str,
        reply_role: str,
        msg: Msg
    ) -> None:
        """Push message to Studio"""
        payload = {
            "runId": run_id,
            "replyId": reply_id,
            "replyName": reply_name,
            "replyRole": reply_role,
            "msg": msg.to_dict()
        }

        response = requests.post(
            f"{self.studio_url}/trpc/pushMessage",
            json=payload,
            timeout=10
        )
        response.raise_for_status()

    def request_user_input(self, run_id: str, agent_id: str, agent_name: str,
                           structured_input=None):
        """Request user input from Studio"""

        request_id = shortuuid.uuid()
        self.input_queues[request_id] = Queue()
        self.input_events[request_id] = Event()

        try:
            response = requests.post(
                f"{self.studio_url}/trpc/requestUserInput",
                json={
                    "requestId": request_id,
                    "runId": run_id,
                    "agentId": agent_id,
                    "agentName": agent_name,
                    "structuredInput": structured_input
                },
                timeout=10
            )
            response.raise_for_status()

            # Wait for user response
            self.input_events[request_id].wait(timeout=300)
            if request_id in self.input_queues:
                return self.input_queues[request_id].get()
            else:
                raise TimeoutError("User input timeout")
        finally:
            # Cleanup
            if request_id in self.input_queues:
                del self.input_queues[request_id]
            if request_id in self.input_events:
                del self.input_events[request_id]


# Usage example
client = StudioClient("http://localhost:3000")

# Register run
client.register_run(
    id="run-12345",
    project="my-project",
    name="custom-agent",
    timestamp=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
    pid=12345,
    status="running"
)

# Create a prompt message
msg = Msg("my-agent", "<system-hint>You should now...</system-hint>", "user")
# Push message
client.push_message(
    run_id="run-12345",
    reply_id="reply-1",
    reply_name="my-agent",
    reply_role="assistant",
    msg=msg
)

# Request user input
user_response = client.request_user_input(
    run_id="run-12345",
    agent_id="agent-1",
    agent_name="My Agent"
)
print(f"User responded: {user_response}")