Skip to content

feat: add schema-driven AGR workflow files inspired by GitHub Actions #83

Description

@jo-hnny

Summary

Add a schema-driven agr workflow capability that executes multiple AGR commands from YAML or JSON files.

The workflow format should reuse the widely familiar GitHub Actions vocabulary and expression style to reduce the learning cost for users and make workflows easier for AI systems to generate. It must remain an AGR-specific local workflow format rather than claim compatibility with GitHub Actions.

Problem

Multi-step AGR tasks currently require shell glue to:

  • execute multiple AGR commands in order;
  • extract resource IDs with jq;
  • pass outputs into later commands;
  • wait for asynchronous resource transitions;
  • clean up resources after success, failure, or cancellation;
  • keep human-readable and machine-readable output separate.

The existing temporary-instance overlay already supports a focused create -> execute -> cleanup flow for instance code run and instance exec, but there is no reusable format for longer workflows such as:

  1. create a Tool;
  2. wait for it to become active;
  3. create an Instance;
  4. upload files;
  5. run code or a remote command;
  6. download results;
  7. delete the Instance and Tool even when an earlier step fails.

Goals

  • Keep the format familiar to users of GitHub Actions.
  • Make workflows straightforward for AI systems to generate from agr schema.
  • Use the existing AGR command IDs, validation, structured results, effects, errors, and cleanup behavior as the source of truth.
  • Support both human-authored YAML and machine-authored JSON without defining two different semantics.
  • Provide deterministic validation, output propagation, cancellation, and cleanup.

Proposed format

Use JSON as the canonical data model and support YAML 1.2 as an equivalent serialization.

Validate both formats with a published JSON Schema 2020-12 document.

Suggested file names:

  • agr-workflow.yaml
  • *.agr.yaml
  • *.agr.json

Example:

$schema: https://cli.tencentcloud.com/agr/schemas/workflow-v1.json

version: 1
name: Run code in a sandbox

inputs:
  tool_id:
    required: true

env:
  LANGUAGE: python

steps:
  - name: Create instance
    id: create
    uses: agr://instance.create
    with:
      tool-id: ${{ inputs.tool_id }}
      wait: true

  - name: Run code
    id: run
    uses: agr://instance.code.run
    with:
      instance-id: ${{ steps.create.outputs.instance_id }}
      language: ${{ env.LANGUAGE }}
      code: print("hello")

  - name: Cleanup
    if: ${{ always() && steps.create.outputs.instance_id != '' }}
    uses: agr://instance.delete
    with:
      instance-id: ${{ steps.create.outputs.instance_id }}
      ignore-not-found: true
      yes: true

agr://<command-id> clearly identifies an AGR command and avoids implying that the file can be executed directly by GitHub Actions.

Familiar vocabulary

Reuse these GitHub Actions concepts where their semantics match:

  • name
  • inputs
  • env
  • steps
  • id
  • uses
  • with
  • if
  • ${{ inputs.* }}
  • ${{ env.* }}
  • ${{ steps.<id>.outputs.* }}
  • success(), failure(), and always()
  • timeout-minutes
  • continue-on-error

The documentation must describe this as:

AGR Workflow is a schema-driven local workflow format inspired by GitHub Actions syntax. It is not a GitHub Actions-compatible runner.

CLI surface

agr workflow init
agr workflow validate -f workflow.agr.yaml
agr workflow run -f workflow.agr.yaml
agr workflow run -f workflow.agr.json
agr workflow run -f workflow.agr.yaml --dry-run
agr workflow schema -o json

Workflow execution should continue to support AGR's normal output contract:

agr workflow run -f workflow.agr.yaml -o text
agr workflow run -f workflow.agr.yaml -o json
agr workflow run -f workflow.agr.yaml -o ndjson

MVP execution semantics

  • Execute steps sequentially in declaration order.
  • Resolve uses against public command IDs exposed by agr schema.
  • Validate with against the selected command schema before performing remote mutations.
  • Allow named command inputs in with, including inputs represented as positional arguments in the interactive CLI.
  • Execute each AGR mutation at most once.
  • Fail fast by default.
  • Preserve context cancellation and process signal handling.
  • Evaluate cleanup steps using always() after success, failure, or cancellation when sufficient inputs are available.
  • Keep progress and diagnostics on stderr.
  • Emit stable per-step events in NDJSON mode and one final workflow envelope in JSON mode.
  • Reuse command handlers or service-level execution internally; do not spawn agr subprocesses and parse their text output.

Outputs

Expose stable command outputs through the familiar step output context:

${{ steps.create.outputs.instance_id }}

Do not require workflow authors to depend directly on internal envelope paths such as:

${{ steps.create.result.Data.InstanceId }}

Command output names should be declared or derived from the AGR command schema and covered by compatibility tests.

Expression subset

The MVP should implement only a small, deterministic subset:

  • property access for inputs, env, and steps;
  • string, number, and boolean literals;
  • equality and inequality;
  • &&, ||, and !;
  • success(), failure(), and always().

Do not evaluate JavaScript, shell expressions, or arbitrary functions.

Validation and safety

  • Use strict YAML 1.2 parsing.
  • Reject duplicate keys, unknown fields, unsupported YAML tags, and invalid command IDs.
  • Validate the entire workflow before executing the first remote mutation.
  • Redact secret values from diagnostics and structured output.
  • Do not allow credentials or secret values to be embedded as a first-class workflow secret store; use existing AGR configuration, environment variables, or a future credential-provider interface.
  • --dry-run should report the ordered steps and known effects without invoking remote mutations.
  • Validation failures must use deterministic AGR structured errors and exit codes.

Non-goals for MVP

  • Full GitHub Actions compatibility.
  • Event triggers such as on.
  • Hosted runners or runs-on.
  • Marketplace actions.
  • Arbitrary local run: shell commands.
  • Multiple jobs, DAG scheduling, implicit parallelism, or matrices.
  • Loops, dynamic fan-out, or reusable remote workflow services.
  • General-purpose CI/CD orchestration.
  • Workflow persistence, remote run history, or resume from checkpoints.

These can be evaluated later only when supported by demonstrated AGR use cases.

Relationship to existing capabilities

  • Reuse agr schema for command discovery and validation.
  • Reuse AGR JSON/NDJSON envelopes, effects, failures, hints, and exit codes.
  • Generalize the existing temporary-instance overlay and cleanup policy instead of building a second cleanup model.
  • Use modeled lifecycle waiting from feat: add --wait for Instance and Tool lifecycle transitions #72 rather than implementing polling logic inside the workflow runner.

Acceptance criteria

  • YAML and JSON representations deserialize into the same internal workflow model.
  • A published JSON Schema provides editor and AI validation for the complete MVP format.
  • agr workflow validate performs complete local validation and makes no remote calls.
  • agr workflow run executes sequential AGR command steps and passes structured outputs to later steps.
  • Cleanup guarded by always() runs after both successful and failed preceding steps.
  • Ctrl-C cancels the active step and enters the eligible cleanup path.
  • Invalid expressions, unknown fields, duplicate keys, invalid command IDs, and command input errors fail before the first mutation.
  • Text output remains human-readable; JSON output is one valid envelope; NDJSON output contains stable step lifecycle events.
  • Secrets are redacted from text, debug, JSON, and NDJSON output.
  • Unit tests cover parsing, schema validation, expression evaluation, output propagation, fail-fast behavior, cleanup, cancellation, and redaction.
  • Integration tests execute a representative create -> run -> cleanup workflow using the real CLI binary.
  • Documentation clearly states that the syntax is inspired by GitHub Actions but is not GitHub Actions compatible.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions