中文EN
ResearchX Docs
English

Agent / Action / Runtime / Visualizer Management

Admin-managed global asset repositories plus project-level agents, actions, runtimes, and project-local visualizer plugins

Agent / Action / Runtime / Visualizer Management

Two Levels

Agent asset management is split into two layers:

  • Global asset repository management: admins maintain shared agent, action, and runtime sources
  • Project asset installation: managers and owners install those assets into the current project

Here, "assets" specifically means:

  • agent
  • action
  • runtime

visualizer plugins currently follow a project-local plugin flow rather than the global asset repository flow.

Admin Global Agent Management

Entry:

  • Agents in the lower-left Workspace menu
  • Page path: /workspace/admin/assets

What admins can do:

  • Add Git or GitHub asset repositories
  • Set repository branches
  • Manually sync a repository
  • Delete a repository
  • Search repositories and assets
  • Edit asset definition files online
  • Edit action entry scripts online
  • Enable or disable a global agent for the current project

Mixed Repository Model

Asset repositories are no longer added separately as actions / agents / runtimes.

A single repository can contain mixed asset types, and the system auto-detects and groups them:

  • actions
  • agents
  • runtimes

The admin page exposes a mixed repository view:

  • one Git repository appears as one card
  • assets inside the card are grouped by kind
  • sync, delete, and edit all operate through this single repository view

Repository Sync and Scanning

After an admin adds an asset repository, the system:

  1. clones or syncs the repository into local asset storage
  2. scans for ACTION.yaml, AGENT.yaml, and RUNTIME.yaml
  3. builds the global asset index
  4. renders parsed assets on the admin page

Notes:

  • a directory containing ACTION.yaml is treated as one action
  • a directory containing AGENT.yaml is treated as one agent
  • a directory containing RUNTIME.yaml is treated as one runtime
  • builtin assets also appear on this page, but the builtin repository cannot be deleted

Online Editing

The admin page currently supports a minimal text editor:

  • click Edit to open a modal editor
  • agent and runtime assets support definition editing
  • action assets support:
    • definition editing
    • entry script editing
    • prompt settings editing (only for executor_type: prompt actions)

When saved, the system:

  • writes the updated file back to disk
  • refreshes the asset index for that repository

Current limitations:

  • text-only editing for now
  • no schema validation, diff, or formatting yet
  • editing builtin assets modifies the local builtin files directly

Project Installation Semantics

Project installation does not reference global definitions live. It copies an installation snapshot into the current project.

Installed project assets are stored in the project workspace at:

.agent/actions/<installed-name>
.agent/agents/<installed-name>
.agent/runtimes/<installed-name>

This means:

  • a project uses only its own installed assets
  • chat agent tools are generated only from agents installed in the current project
  • later global repository updates do not auto-update existing project installations
  • projects must reinstall or refresh their installed snapshot to pick up new asset versions

Enabling a Global Agent

If you want a global agent to be available in the current project without copying it into a local installation snapshot, use Enable global.

What this does:

  • Stores a global enablement record for the current project
  • Does not create a new install directory under .agent/agents
  • Lets chat agent tools reference the global agent definition directly
  • You can later turn it off with Disable global

Visualizers (Project-local Plugins)

visualizer plugins extend file preview with custom Web-based renderers, for example structure viewers, spreadsheet-style previews, or special-format renderers.

Their lifecycle differs from agent/action/runtime:

  • they are not installed from global asset repositories
  • they live directly inside the current project's .agent/visualizers
  • the system auto-discovers them inside the project
  • file preview decides whether to hand off rendering based on the plugin's declared match rules

Recommended directory structure:

.agent/visualizers/
  <namespace>/<visualizer-name>/
    VISUALIZER.yaml
    web/
      index.html
      ...

Discovery rules:

  • any directory containing VISUALIZER.yaml is treated as one visualizer
  • the match section inside VISUALIZER.yaml declares which files it supports
  • if more than one visualizer matches the same file, the host chooses a default based on rules and priority

Project Visualizers Management

Entry:

  • the Agents modal in the project workspace header
  • then the Visualizers tab

What you can do:

  • inspect auto-discovered visualizers in the current project
  • review manifest path, web entry path, and match rules
  • select multiple visualizers and download them as a zip package
  • upload a visualizer zip archive into the current project
  • import visualizers directly from another project

Notes:

  • the list reflects the visualizers currently discovered under .agent/visualizers
  • they are project-local assets and are not auto-synced across projects
  • this works best for project-specific preview plugins

Boundaries Between Action, Agent, and Runtime

  • agent
    • defines user-facing task semantics and step orchestration
  • action
    • defines the business operation a step executes
    • supports independent container execution configuration
  • runtime
    • defines where code runs: container environment, remote worker, or cluster

In the process-first model:

  • runtime answers "where does it run?"
  • action answers both "what runs?" and "how does it start?"

Action-Level Container Configuration

Container configuration is now supported at the Action level. Define it via config.container in ACTION.yaml:

config:
  container:
    image: python:3.12-slim
    workdir: /workspace
    gpu: 1
    mounts:
      - source: ./models
        target: /workspace/models

Priority:

  • Action-level config.container takes precedence over Runtime configuration
  • If the Action does not define a GPU count, the runtime default config.resources.gpu is used
  • If neither Action nor Runtime defines a GPU count, the project's saved GPU count is used

GPU notes:

  • config.container.gpu and config.resources.gpu must be positive integers
  • Project GPU driver and memory settings are reused as metadata for container-backed action runs

Typical binding:

  • runtime.container.default.v1 + config.container.image=python:3.12-slim + entry.command=python3 + entry.path=./main.py
  • runtime.container.default.v1 + config.container.image=node:20-alpine + entry.command=node + entry.path=./main.mjs
  • runtime.container.default.v1 + config.container.image=python:3.12-slim + entry.command=Rscript + entry.path=./main.R

Dependency Completeness

Chat does not expose every installed agent to the model.

Only dependency-complete agents are exposed as agent tools:

  • template agents: all referenced actions and runtimes must be available

If an agent is installed but does not appear in chat, check:

  • whether the required action is installed
  • whether the action's runtime is installed
  • whether a container action's image and entry script are actually runnable

Manual Agent Execution

Besides triggering agents through chat, you can also run them manually:

  1. Click the Agent entry in the project workspace header
  2. Select the agent to run
  3. Fill in required parameters
  4. Results appear in the message area after execution

Use cases:

  • Precise control over agent input parameters
  • Testing or debugging specific agents
  • Running standalone tasks independent of conversation context

Single-Action Execution Mode

Besides running a full Agent, the system supports directly executing individual Actions:

  • Trigger a single Action through specific syntax in chat
  • No need to go through full Agent step orchestration
  • Suitable for simple single-operation tasks

Notes:

  • Single-action execution is for tasks that don't require multi-step orchestration
  • Results are returned directly to the conversation
  • The required Action must be installed in the project

Step-Level Conditional Execution (when Expressions)

Agent steps support conditional execution via the when field:

steps:
  - step_id: analyze
    action_ref: data_analysis
    input:
      data: "${input.dataset}"
  
  - step_id: generate_report
    action_ref: report_generator
    when: "input.generate_report === true"
    input:
      analysis: "${steps.analyze.output}"

when expression features:

  • JavaScript expression evaluation
  • Context includes input (user input) and steps (previous step outputs)
  • Supports placeholders: ${input.field} and ${steps.step_id.output.field}
  • Expressions run inside the project's persistent container; unavailable containers or evaluation failures are treated as false
  • Steps with when evaluating to false are skipped and show Skipped status
  • Steps without when execute by default

Typical use cases:

  • Decide whether to run optional steps based on user input
  • Control downstream flow based on previous step outputs
  • Implement conditional branching logic

Schema Auto-Merge (merge_from_actions)

When an Agent wraps existing Actions without new logical inputs, use merge_from_actions to automatically merge Action input schemas. Entries use the same reference form as steps[].action_ref: either an Action name or a one/two-segment installed Action path such as repo_a/fetch_abstract.

name: paper-summary-agent
merge_from_actions:
  - fetch_abstract
  - summarize_abstract
inputs:
  doi:
    type: string
  paper_url:
    type: string
    optional: true

Merge rules:

  • Agent's inputs declares only field names and types referenced by ${input.xxx}
  • description and default are auto-merged from Action's inputs
  • Agent's own properties take precedence
  • The runtime field output_dir may be passed with a ticket input to choose where this run writes results; when omitted, the platform creates agents-output/<YYYY-MM-DD>/<agent-name>-<ticket-id> using the AgentRun creation date

Benefits:

  • Reduce duplication
  • Maintain schema consistency
  • Automatically inherit new fields when Actions update

Step Output References

Data passing between steps supports two forms:

Single field reference:

input:
  analysis_result: "${steps.analyze.output.result}"

Full output reference (RFC-0012):

input:
  full_output: "${steps.analyze.output}"

Full output reference is useful for:

  • Passing complete previous step output to subsequent steps
  • Dynamic output structures
  • Simplifying complex object passing

Prompt Action Editor

Installed Prompt Actions support online editing of prompt settings:

Operation path:

  1. Click the relevant entry in the project workspace header
  2. Find the installed Prompt Action (executor_type is prompt)
  3. Click the Edit button
  4. In the popup editor, modify:
    • Output mode: select json or text
    • Prompt user: user prompt content
    • Prompt system: system prompt content (optional)
  5. Save to update ACTION.yaml

Output mode description:

  • json: keeps the current declared output shape, requiring the model to return strictly matching structured JSON
  • text: automatically rewrites the declared output shape to { content: string }, the model returns plain text and wraps it in the content field

Use cases:

  • Quickly adjust Prompt Action prompt content
  • Switch output mode (structured JSON vs plain text)
  • Debug or optimize generation results

Notes:

  • Only works for installed Prompt Actions
  • Switching to text mode modifies the declared output shape
  • Need to re-run the Action to see the new prompt effect

Persistent Container Execution (Without runtime_ref)

Process Actions can now execute directly in the project's persistent container without explicit runtime_ref configuration.

Automatic Execution Mode Selection:

  • When an Action does not configure runtime_ref, the system automatically uses the project's persistent container
  • When an Action configures runtime_ref, it looks up and uses the specified runtime as before
  • When an Action defines config.container.image, it uses ephemeral container execution
  • When an Action does not define config.container.image, it uses persistent container execution

Benefits:

  • Simplifies Action definitions — no need to repeat runtime_ref for every Action using the persistent container
  • Automatically reuses dependencies and environment already installed in the project's persistent container
  • Maintains state continuity across conversations

Example - Container Action Without runtime_ref:

name: data-analysis
title: Data Analysis
description: Analyze data using Python in the persistent container.
executor_type: process
# runtime_ref is no longer needed — automatically uses the project persistent container
config:
  container:
    image: python:3.12-slim  # defines image → uses ephemeral container
    workdir: /workspace
entry:
  kind: script
  path: ./analyze.py
  command: python3
version: 1
inputs:
  dataset:
    type: string
outputs:
  result:
    type: string
    value: ${read_string("output/result.txt")}

Example - Persistent Container Without image:

name: run-existing-script
title: Run Existing Script
description: Run an existing script in the persistent container, reusing the container environment.
executor_type: process
# No runtime_ref and no config.container.image defined
# Automatically uses the project's persistent container
entry:
  kind: script
  path: ./scripts/process.py
  command: python3
version: 1
inputs:
  input_file:
    type: string
outputs:
  output_file:
    type: file
    value: ${file("output/output.json")}

Notes:

  • Persistent container execution requires the project to have persistent container environment enabled
  • If the persistent container is unavailable, execution fails with an error
  • Ephemeral container execution (when image is defined) behaves the same as the original docker run --rm flow
  • In chat, only Actions with an entry are exposed as available tools

Container Image Editor

Installed Actions support online editing of container image configuration:

Operation path:

  1. Click the relevant entry in the project workspace header
  2. Find the installed Action
  3. Click edit container image
  4. Modify the image name (e.g., python:3.12-slimpython:3.11-slim)
  5. Save to update the config.container.image field in ACTION.yaml

Use cases:

  • Quickly switch between Python, Node, or other runtime environment versions
  • Use different base images for debugging
  • Customize container environments

Notes:

  • Only works for installed Actions
  • Modified images take effect on subsequent Action executions
  • Requires Runtime that supports container execution

Agent Authoring Skill

In dev mode, the system exposes the built-in read-only agent-authoring skill for creating and modifying Agents:

When to use:

  • Create new project Agents
  • Modify or extend existing Agents
  • Create supporting Actions

Core capabilities:

  • Generate Agent and Action files that match the install layout
  • Reuse existing Actions to avoid duplicate development
  • Generate executable entry scripts (supports Node, Python, R)
  • Automatically configure container settings and runtime references

Usage:

  1. Switch the project to dev mode
  2. Describe Agent requirements in chat
  3. The skill writes complete Agent definitions and Action files directly into the project install layout
  4. Files are saved to .agent/agents/ and .agent/actions/ directories

Generation specifications:

  • Agents must contain at least one executable step
  • Action entry scripts should receive inputs through WDL-style entry.args / entry.env by default, and should materialize final results through declared outputs
  • Process Actions default to the project's persistent container by omitting runtime_ref; use runtime.container.default.v1 plus config.container.image only for an ephemeral container with a specific image
  • Declared outputs should exactly match the final values produced by the action
  • Dynamic file outputs can be driven from manifest path fields, but the declared output should still be type: file or type: array[file], for example file(read_json("output/manifest.json").report_path) or glob(read_json("output/manifest.json").chart_pattern)

Asset Definition Formats

Agent Definition

Agent definition file AGENT.yaml contains the following fields:

Required fields:

  • name: Machine-safe identifier (lowercase letters, numbers, ., _, -)
  • title: Human-readable title
  • description: One-sentence description of user-facing task semantics
  • task_type: Stable machine-readable task label
  • version: Version number (usually 1)
  • inputs: JSON Schema for input parameters (type: object)
  • steps: Ordered list of execution steps
  • result: Declares workflow outputs. Outputs use the same WDL-style type/value shape as Action outputs and may reference input, steps.<step_id>.output, file(...), glob(...), read_string(...), or read_json(...). result.step_id is not supported.

Step fields:

  • step_id: Step identifier
  • title: Step title
  • action_ref: Referenced action name
  • input: Input parameter mapping (supports placeholders)
  • depends_on: Dependent steps (optional)
  • timeout_sec: Timeout in seconds (optional)
  • when: Conditional expression (optional)

Example:

name: paper-summary-agent
title: Paper Summary Agent
description: Fetch an abstract for a paper title and return a concise structured summary.
task_type: paper_summary_agent
version: 1
merge_from_actions:
  - fetch_abstract
  - summarize_abstract
inputs:
  paper_title:
    type: string
steps:
  - step_id: fetch_abstract
    title: Fetch abstract
    action_ref: fetch_abstract
    input:
      paper_title: ${input.paper_title}
    timeout_sec: 300
  - step_id: summarize_abstract
    title: Summarize abstract
    action_ref: summarize_abstract
    input:
      paper_title: ${input.paper_title}
      abstract_text: ${steps.fetch_abstract.output.abstract_text}
    depends_on:
      - fetch_abstract
    timeout_sec: 300
result:
  outputs:
    paper_title:
      type: string
      value: ${steps.summarize_abstract.output.paper_title}
    summary:
      type: string
      value: ${steps.summarize_abstract.output.summary}

Action Definition

Action definition file ACTION.yaml contains the following fields:

Required fields:

  • name: Machine-safe identifier
  • title: Human-readable title
  • description: Brief explanation of business function
  • executor_type: Executor type (process or prompt)
  • version: Version number
  • inputs: Declared action input fields keyed by name
  • outputs: Declared action outputs. Each field defines both its type and how the final value is produced or collected

process type additional fields:

  • runtime_ref: Referenced runtime name
  • entry: Entry configuration

prompt type additional fields:

  • prompt: Prompt configuration (contains user and optional system)

executor_type: process (Script Execution)

Traditional script execution mode, requires runtime and entry configuration:

Entry configuration:

entry:
  kind: script
  path: ./index.mjs
  command: node
  args:
    - ${input.query}
    - ${input.days_back}
    - ${input.max_results}
  env:
    OUTPUT_DIR: ${context.files.output_dir}
  stdin: none

Container configuration (optional):

config:
  container:
    image: python:3.12-slim
    workdir: /workspace
    gpu: 1

config.container.gpu is an optional per-action GPU count override. It must be a positive integer. When omitted, container actions can fall back to runtime.config.resources.gpu, then to the project's saved GPU count.

Example - Container execution:

name: fetch_pubmed_container
title: Fetch PubMed Container
description: Generate a normalized recent-literature JSON file and concise summary from a query inside the container runtime.
executor_type: process
runtime_ref: runtime.container.default.v1
config:
  container:
    image: python:3.12-slim
    workdir: /workspace
    gpu: 1
entry:
  kind: script
  path: ./index.mjs
  command: node
  args:
    - ${input.query}
    - ${input.days_back}
    - ${input.max_results}
  env:
    OUTPUT_DIR: ${context.files.output_dir}
  stdin: none
version: 1
inputs:
  query:
    type: string
  days_back:
    type: number
    optional: true
  max_results:
    type: number
    optional: true
outputs:
  summary:
    type: string
    value: ${read_json("output/manifest.json").summary}
  count:
    type: number
    value: ${read_json("output/manifest.json").count}
  result_file:
    type: file
    value: ${file("output/pubmed_results.json")}

Manifest-driven outputs are also supported:

outputs:
  report_file:
    type: file
    value: ${file(read_json("output/manifest.json").report_path)}
  chart_files:
    type: array[file]
    value: ${glob(read_json("output/manifest.json").chart_pattern)}

The manifest fields above are only collection inputs. The user-visible outputs remain standard file descriptors because the declared fields are type: file and type: array[file].

Optional outputs fall back to null when their value cannot be resolved:

outputs:
  has_report:
    type: boolean
    value: ${exists(read_json("output/manifest.json").report_path)}
  report_file:
    type: file
    optional: true
    value: ${file(read_json("output/manifest.json").report_path)}

executor_type: prompt (Prompt Execution)

Config-only model invocation without writing scripts. Suitable for:

  • Structured text generation (marketing copy, report summaries, etc.)
  • Data extraction and transformation
  • Text classification and tagging
  • Content rewriting and polishing
  • Chat-backed actions that benefit from scoped tools, skills, or agent delegation

Features:

  • No runtime_ref or entry required
  • Define system and user prompts via prompt field
  • Automatically uses project default model
  • Reuses the shared chat runtime instead of a one-shot model call
  • Can scope shared skills, actions, and agents through optional capabilities
  • Default output mode is structured output matching the declared outputs shape, submitted through the runtime's internal structured-output tool
  • prompt.output_mode: text is also supported for plain-text results; the runtime wraps the final model text in the declared content field

Example - Marketing copy generation:

name: generate_marketing_copy
title: Generate Marketing Copy
description: Generate structured marketing copy for a given topic.
executor_type: prompt
version: 1

inputs:
  topic:
    type: string
    description: The topic or product to generate copy for

outputs:
  title:
    type: string
    description: Main headline for the copy
  bullets:
    type: array[string]
    description: Key selling points

prompt:
  system: |
    You are a professional marketing copywriter.
    Finish by submitting the final structured result through the runtime's structured-output tool.
    The submitted fields must match the declared outputs exactly.
  user: |
    Generate marketing copy for: ${input.topic}
capabilities:
  expose_all_builtin_tools: true
  expose_all_skills: true
  expose_all_actions: true
  expose_all_agents: true

Example - Plain text prompt action with fixed wrapper:

name: summarize_topic
title: Summarize Topic
description: Generate a plain text summary and store it in the declared content field.
executor_type: prompt
version: 1

inputs:
  topic:
    type: string

outputs:
  content:
    type: string

prompt:
  output_mode: text
  user: |
    Write a concise summary for: ${input.topic}

By default, omitted capability fields expose nothing. That includes built-in base tools such as read, bash, edit, write, and web_search. Use expose_all_builtin_tools, expose_all_skills, expose_all_actions, or expose_all_agents to expose a whole category, or use allowed_* arrays as exact allowlists.

Capabilities Fields Detailed:

FieldTypeDefaultDescription
inherit_project_skillsbooleanfalseWhether to inherit project-installed skills. Set to true only when the prompt action should see project skills beyond explicit allowed_skills
expose_all_builtin_toolsbooleanfalseWhether to expose all built-in base tools available to prompt actions
expose_all_skillsbooleanfalseWhether to expose all project-installed skills (effective when inherit_project_skills=true)
expose_all_actionsbooleanfalseWhether to expose all project-installed actions
expose_all_agentsbooleanfalseWhether to expose all project-installed agents
allowed_builtin_toolsstring[][]Exact allowlist: built-in tool names such as read, bash, edit, write, web_search
allowed_skillsstring[][]Exact allowlist: list of allowed skill names
allowed_actionsstring[][]Exact allowlist: list of allowed action names
allowed_agentsstring[][]Exact allowlist: list of allowed agent names

Priority Rules:

  • When inherit_project_skills=false, only allowed_skills whitelist is used
  • When expose_all_builtin_tools=true, all built-in base tools are exposed
  • When inherit_project_skills=true + expose_all_skills=true, all project skills are exposed
  • When inherit_project_skills=true + expose_all_skills=false + allowed_skills has values, whitelist is used
  • When both expose_all_* and allowed_* are set, expose_all_* takes precedence

UI Display: In the Action detail panel in the project workspace, you can see the following capabilities information:

  • inherits skills: Shows whether project skills are inherited (yes / no)
  • allowed builtin tools: Shows the list of allowed built-in base tools
  • allowed skills: Shows the list of allowed skills
  • allowed actions: Shows the list of allowed actions
  • allowed agents: Shows the list of allowed agents

Self-Reference Warning: If a prompt action includes its own name in allowed_actions, the system displays a warning in the Action detail panel about potential recursive self-call risks. It's recommended to remove self-references or ensure clear termination conditions.

Example - Text summarization:

name: summarize_text
title: Summarize Text
description: Generate a concise summary of the input text.
executor_type: prompt
version: 1

inputs:
  text:
    type: string
    description: The text to summarize
  max_length:
    type: number
    description: Maximum summary length in words
    optional: true
    default: 100

outputs:
  summary:
    type: string
  key_points:
    type: array[string]

prompt:
  user: |
    Summarize the following text in at most ${input.max_length} words.
    Include a short summary plus key points in the final structured result.
    
    Text: ${input.text}
capabilities:
  allowed_skills: ["summarization"]
  allowed_actions: []
  allowed_agents: []

Prompt template syntax:

  • ${input.field_name}: Insert input parameter value
  • ${input.nested.field}: Read nested object fields using dot notation
  • ${input.field | json}: Render a value as pretty JSON
  • Automatic formatting for strings, numbers, and booleans
  • Complex objects are automatically converted to JSON strings
  • Unsupported ${...} expressions are rejected instead of being evaluated as JavaScript

Execution flow:

  1. Validate input parameters against inputs
  2. Render prompt.system and prompt.user templates
  3. Build a scoped shared-chat runtime using optional capabilities
  4. Run the project default model with shared tools, skills, and agents when allowed
  5. Capture the final structured result from the runtime's internal structured-output tool
  6. Validate output against the declared output shape
  7. Return structured result

Use case comparison:

Scenarioprocessprompt
File system operations
External API calls
Complex computation logic
Pure text transformation/generation
No code required
Quick prototyping

Important notes:

  • In prompt.output_mode: json, the final structured result is submitted through an internal tool call rather than parsed from assistant text
  • Output structure must strictly match the declared output shape
  • Prompt actions can use shared tools, skills, and agents when allowed by capabilities
  • Cannot access file system or external services

Action Entry Script Specification (process type)

Entry scripts should follow these conventions:

Input: Prefer WDL-style command inputs on entry.args and entry.env.

entry:
  kind: script
  path: ./index.mjs
  command: node
  args:
    - ${input.paper_title}
  env:
    OUTPUT_DIR: ${context.files.output_dir}
  stdin: none

Template expressions support ${input.field}, ${input.nested.field}, ${config.field}, ${context.field}, and | json. If a whole argument resolves to an array, it expands into multiple argv entries. Use stdin: json only when the script needs the complete { input, config, context } payload.

Output:

  • Preferred: materialize files under context.files.output_dir and let the runtime collect the declared outputs
  • Relative file expressions in outputs.value are resolved from the run output directory; returned file descriptors are still project-workspace-relative
  • Process success is determined by a zero exit code plus successful outputs collection
  • Failures should write a readable message to stderr and exit non-zero

Failure:

{
  "status": "failed",
  "error": {
    "code": "INVALID_INPUT",
    "message": "paper_title is required."
  }
}

Node.js Example (outputs-first pattern):

import { mkdir, writeFile } from "node:fs/promises";
import path from "node:path";

async function main() {
  const title = (process.argv[2] ?? "").trim();
  const outputDir = process.env.OUTPUT_DIR || "/workspace";

  if (!title) {
    throw new Error("paper_title is required.");
  }

  const resultsDir = path.join(outputDir, "output");
  await mkdir(resultsDir, { recursive: true });
  await writeFile(path.join(resultsDir, "abstract.txt"), `Abstract for ${title}: ...`, "utf8");
}

main()
  .then(() => {
    process.stdout.write("ok");
  })
  .catch((error) => {
    process.stderr.write(`${error instanceof Error ? error.message : "Unknown error"}\n`);
    process.exit(1);
  });

Runtime Definition

Runtime definition file RUNTIME.yaml describes the execution environment:

Field descriptions:

  • name: Runtime identifier. Actions reference this value through runtime_ref.
  • title: Human-readable title shown in asset lists.
  • kind: Runtime type. Process Actions currently support container runtimes only.
  • source: Source marker such as system_builtin, user_defined, or model_generated.
  • status: Asset lifecycle marker such as published. Runtime execution does not currently use this as a hard enable/disable switch.
  • config: Runtime configuration object.
    • protocol: Communication protocol. Must be stdio_json.
    • env: Environment variables merged into process action execution.
    • timeouts.max_execution_sec: Default wall-clock timeout in seconds. A step-level timeout_sec overrides it. Use 0 to disable the application-layer wait timeout.
    • resources.cpu: CPU amount requested for the action execution target.
    • resources.memory_mb: Memory amount in MB.
    • resources.disk_gb: Disk amount in GB. This mainly affects ephemeral container resource admission.
    • resources.gpu: Optional default GPU count for this runtime. Must be a positive integer when provided.
    • container: Parsed for compatibility, but the current executor does not use runtime-level container.image, container.workdir, or container.mounts to launch actions. Put image, workdir, and action-specific container settings on ACTION.yaml under config.container.
  • version: Definition version marker.

Lookup order:

  • If an Action has runtime_ref, ResearchX first checks the project-local .agent/runtimes/<runtime_ref>/RUNTIME.yaml.
  • If no project-local runtime exists, ResearchX falls back to the global runtime catalog.
  • A project-local runtime with the same name as a global runtime acts as a project-specific override.
  • If an Action omits runtime_ref, it uses the project persistent container path and does not read the global runtime.container.default.v1 definition.

Example - Container Runtime:

{
  "name": "runtime.container.default.v1",
  "title": "Container Runtime",
  "kind": "container",
  "source": "system_builtin",
  "status": "published",
  "config": {
    "protocol": "stdio_json",
    "container": {
      "image": "python:3.12-slim",
      "workdir": "/workspace"
    },
    "timeouts": {
      "max_execution_sec": 6000
    },
    "resources": {
      "cpu": 2,
      "memory_mb": 2048,
      "disk_gb": 4,
      "gpu": 1
    }
  },
  "version": 1
}

In the example above, protocol, timeouts, and resources affect execution. The container.image and container.workdir values are currently informational/forward-compatible; the effective container image and workdir should be defined on each process Action:

executor_type: process
runtime_ref: runtime.container.default.v1
config:
  container:
    image: python:3.12-slim
    workdir: /workspace

File Organization Structure

Asset files must be organized in the following structure:

.agent/
├── agents/
│   └── <agent-name>/
│       └── AGENT.yaml
├── actions/
│   ├── <action-name>/
│   │   ├── ACTION.yaml
│   │   └── index.mjs  # or index.py, main.R, etc.
│   └── <another-action>/
│       ├── ACTION.yaml
│       └── index.mjs
└── runtimes/
    └── <runtime-name>/
        └── RUNTIME.yaml

Rules:

  • Each asset uses its own directory
  • Directory name should match the asset name
  • Place ACTION.yaml and entry script in the same directory
  • Do not cross-reference files between action directories
  • Maintain shared assets in Git repositories instead of manually curating long-lived project .agent directories
  • After changing a global asset, sync and validate it in admin first, then reinstall it in projects as needed
  • Keep action entry scripts inside the action's own directory; do not cross-reference other action directories
  • Treat runtimes as environment definitions; startup commands belong on the action entry itself
  • Process-based actions should receive explicit command inputs through entry.args / entry.env by default, materialize declared artifacts in the workspace, and let the runtime resolve final results through outputs; reserve stdin JSON for actions that explicitly need the full payload
  • Write agent title and description as user task semantics, not internal implementation notes
  • Use when conditions for flexible execution flow control
  • Use merge_from_actions to reduce schema duplication

Agent Import/Export

Installed project Agents support export and batch import for cross-project migration and backup.

Export Agents

In the project Agents modal, you can:

  1. Select installed Agents to export (multi-select supported)
  2. Click the export button
  3. The system packages selected Agents, their dependent Actions, and project-local runtime dependencies as a zip archive for download

Exported zip file structure:

agents-20260401-120000.zip
├── runtimes/               # Project-local runtimes referenced by bundled actions
│   └── <runtime-name>/
│       └── RUNTIME.yaml
├── agents/                 # Agents directory
│   └── <agent-name>/       # Agent directory
│       ├── AGENT.yaml
│       └── ...other files
└── actions/                # Actions directory
    └── <action-name>/      # Action directory
        ├── ACTION.yaml
        └── index.mjs

Export automatically includes dependencies:

  • The system analyzes Actions referenced in each Agent's AGENT.yaml
  • Automatically packages related Actions into the export
  • Automatically packages project-local Runtimes referenced by bundled Actions
  • Global-only runtimes are not copied into the archive; the target project resolves them from the global catalog
  • Ensures imported Agents can execute properly

Runtime import behavior:

  • Bundled runtimes are installed before bundled actions and agents.
  • If the target project already has the same runtime and its RUNTIME.yaml content matches, import reuses it.
  • If the target project already has the same runtime with different content, import stops with a conflict instead of overwriting silently.
  • When importing Agents into an admin asset repository, bundled runtimes are imported into the matching runtime repository in the selected repository group.

Import Agents from Other Projects

Besides importing zip archives, you can also directly import installed Agents from other projects:

Operation path:

  1. Click the "Import from Project" button in the project Agents modal
  2. Select a source project from the dropdown (shows all accessible projects)
  3. The system automatically loads the list of installed Agents from the source project
  4. Review Agent name, title, description, and installation path
  5. Click the "Import from Project" button to import a single Agent

Import features:

  • Agents with matching names show a "Name Match" badge for easy identification
  • Sorted by name match priority, then alphabetically by title
  • Only shows installed Agents
  • Automatically includes dependent Actions and project-local Runtimes when importing

Use cases:

  • Quickly copy validated Agents from other projects
  • Avoid reinstalling Agents and their dependent Actions and Runtimes
  • Team members share pre-configured Agent combinations

Notes:

  • Import fails if an Agent or Action with the same name already exists in the target project
  • Imported Agents use the current version snapshot from the source project
  • Requires access permissions to the source project to see its Agents

Import Agents

In the project Agents modal, you can:

  1. Click the import button
  2. Upload an Agents zip archive
  3. The system installs bundled Runtimes, Actions, and Agents

Import process:

  • Reads runtimes/, actions/, and agents/ directories from the zip file
  • Copies bundled Runtimes, Actions, and Agents to the project's .agent/
  • Creates database installation records

Notes:

  • If an Agent or Action with the same name already exists in the project, import will fail with detailed conflict information
  • Imported Runtimes, Actions, and Agents are immediately available in the project
  • Verify asset source trustworthiness before importing
  • Import installs all Actions included in the zip, even if some Actions are not directly referenced by Agents
  • Use the agent-authoring skill in dev mode for rapid Agent creation and iteration

Action Import/Export

Installed project Actions support export and batch import, aligned with the Agents import/export flow.

Export Actions

In the Actions tab of the project Assets modal, you can:

  1. Check installed Actions to export (multi-select and "select all visible" supported)
  2. Click "Download selected actions"
  3. The system packages selected Actions and project-local runtime dependencies as a zip archive for download

Exported action archives may include:

actions-20260401-120000.zip
├── runtimes/
│   └── <runtime-name>/
│       └── RUNTIME.yaml
└── actions/
    └── <action-name>/
        ├── ACTION.yaml
        └── index.mjs

Project-local Runtimes referenced by exported Actions are bundled. Global-only runtimes are left as global dependencies.

Import Actions from Other Projects

Besides importing zip archives, you can directly import installed Actions from other projects:

  1. Click "Import from project" in the Actions tab
  2. Select a source project
  3. The system loads installed Actions from the source project
  4. Click import to install a single Action into the current project

Import Actions Zip

  1. Click "Import action archive"
  2. Upload a previously exported Actions zip file
  3. The system automatically parses and installs the Actions

Notes:

  • Import fails if an Action with the same name already exists in the project
  • Bundled Runtimes are installed before Actions. Existing same-name runtimes with different content cause an import conflict.
  • Verify asset source trustworthiness before importing