From 25b2f8f7c5529378e751b808952edab7e2f58312 Mon Sep 17 00:00:00 2001 From: Rohan Gupta <52221549+thisrohangupta@users.noreply.github.com> Date: Mon, 23 Feb 2026 22:16:01 -0800 Subject: [PATCH 1/6] Add agent triggers design document Added a comprehensive design document for agent triggers that outlines event-driven execution for Harness agents, including key design decisions, schema changes, event references, and examples. --- agent-design.md | 673 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 673 insertions(+) create mode 100644 agent-design.md diff --git a/agent-design.md b/agent-design.md new file mode 100644 index 0000000..31ac21e --- /dev/null +++ b/agent-design.md @@ -0,0 +1,673 @@ +# Agent Triggers: Event-Driven Execution for Harness Agents + +## Overview + +This document defines trigger support for Harness Agent Templates. Triggers allow agents (and pipelines) to automatically execute in response to platform events — a pipeline fails, a PR is opened, costs spike, a vulnerability is found, or a user mentions an agent in a comment. + +The design extends the existing [pipeline spec schema](https://github.com/bradrydzewski/spec/blob/master/schema/schema.ts) — agents reuse the Pipeline type, and Harness system events are added to the existing `on:` stanza that pipelines already support. + +--- + +## Key Design Decisions + +1. **Agent = Pipeline.** The top-level schema adds `agent?: Pipeline` as an alias. Agents use the exact same YAML structure as pipelines, keeping Studio compatibility. +2. **`on:` lives inside `pipeline.yaml`.** No separate trigger file. The `pipeline.on` field (already in the spec) is where events are declared. +3. **Shared event types.** Harness system events (CI failures, cost spikes, vulnerabilities) are added to the same `EventType` union that already contains GitHub events (`push`, `pull_request`, etc.). Both pipelines and agents can use any event. +4. **Progressive complexity.** Following the existing `On` type pattern: `EventType | Event[] | Event` — simple string, list, or structured with filters. + +--- + +## Schema Changes + +### Top-level: add `agent` as Pipeline alias + +From [schema.ts](https://github.com/bradrydzewski/spec/blob/master/schema/schema.ts#L22): + +```typescript +export interface Schema { + version?: string | number; + pipeline?: Pipeline; ++ agent?: Pipeline; // Agent is an alias for Pipeline + // ... existing fields +} +``` + +In YAML, an agent template can use either top-level key: + +```yaml +# As a pipeline (existing) +version: 1 +pipeline: + on: pull_request + stages: [...] + +# As an agent (new — identical structure) +version: 1 +agent: + on: pull_request + stages: [...] +``` + +### Pipeline.on: already exists + +From [pipeline.ts](https://github.com/bradrydzewski/spec/blob/master/schema/pipeline.ts): + +```typescript +export interface Pipeline { + on?: On; // Already in the spec + stages?: Stage[]; + inputs?: Record; + clone?: Clone; + // ... +} +``` + +### EventType: extend with Harness system events + +From [on.ts](https://github.com/bradrydzewski/spec/blob/master/schema/on.ts), the existing type: + +```typescript +export type On = EventType | Event[] | Event; +export type Event = EventType | EventLong; + +export type EventType = + // ── Existing GitHub events ── + | "push" + | "pull_request" + | "pull_request_review" + | "pull_request_review_comment" + | "pull_request_target" + | "issue_comment" + | "schedule" + | "workflow_dispatch" + | "repository_dispatch" + // ... other GitHub events + + // ── NEW: Harness CI events ── + | "pipeline_failed" + | "build_failed" + | "test_failed" + + // ── NEW: Harness CD events ── + | "deploy" + | "deploy_failed" + | "canary" + | "rollback" + | "slo_breach" + | "post_deploy" + + // ── NEW: Harness CCM events ── + | "cost_spike" + | "budget_exceeded" + | "cost_anomaly" + + // ── NEW: Harness STO events ── + | "vulnerability_found" + | "scan_complete" + | "severity_threshold" + + // ── NEW: Harness Platform events ── + | "comment_mention" + | "repo_created" + | "flag_stale"; +``` + +> **Naming convention:** Harness events use `snake_case` to be consistent with the existing GitHub event names (`pull_request`, `issue_comment`, `check_run`, etc.). No module prefix needed — the event names are unique and self-descriptive. + +### EventLong: extend with Harness event filters + +```typescript +export interface EventLong { + // ── Existing GitHub events ── + push?: PushFilter; + pull_request?: PullRequestFilter; + schedule?: ScheduleFilter; + // ... existing fields + + // ── NEW: Harness CI events ── + pipeline_failed?: PipelineFailedFilter; + build_failed?: PipelineFailedFilter; + test_failed?: PipelineFailedFilter; + + // ── NEW: Harness CD events ── + deploy?: DeployFilter; + deploy_failed?: DeployFilter; + canary?: DeployFilter; + rollback?: DeployFilter; + slo_breach?: SloFilter; + post_deploy?: DeployFilter; + + // ── NEW: Harness CCM events ── + cost_spike?: CostFilter; + budget_exceeded?: BudgetFilter; + cost_anomaly?: CostFilter; + + // ── NEW: Harness STO events ── + vulnerability_found?: VulnerabilityFilter; + scan_complete?: ScanFilter; + severity_threshold?: ScanFilter; + + // ── NEW: Harness Platform events ── + comment_mention?: CommentMentionFilter; + repo_created?: EventFilter; + flag_stale?: EventFilter; +} +``` + +### New filter interfaces + +```typescript +// CI filters +export interface PipelineFailedFilter { + repos?: string | string[]; + branches?: string | string[]; + pipelines?: string | string[]; +} + +// CD filters +export interface DeployFilter { + services?: string | string[]; + environments?: string | string[]; +} + +export interface SloFilter { + services?: string | string[]; + slos?: string | string[]; +} + +// CCM filters +export interface CostFilter { + resources?: string | string[]; + "threshold-percent"?: number; +} + +export interface BudgetFilter { + budgets?: string | string[]; +} + +// STO filters +export interface VulnerabilityFilter { + repos?: string | string[]; + severity?: string | string[]; // critical, high, medium, low + "scan-types"?: string | string[]; +} + +export interface ScanFilter { + repos?: string | string[]; + "scan-types"?: string | string[]; +} + +// Platform filters +export interface CommentMentionFilter { + agents?: string | string[]; // filter by mentioned agent name + repos?: string | string[]; +} +``` + +--- + +## Event Reference + +### CI events + +| Event | Description | Filter fields | Event payload | +|-------|-------------|---------------|---------------| +| `pipeline_failed` | A CI pipeline execution has failed | `repos`, `branches`, `pipelines` | `repo`, `branch`, `executionId` | +| `build_failed` | A build step has failed | `repos`, `branches`, `pipelines` | `repo`, `branch`, `executionId` | +| `test_failed` | Test execution has failed | `repos`, `branches`, `pipelines` | `repo`, `branch`, `executionId` | + +### CD events + +| Event | Description | Filter fields | Event payload | +|-------|-------------|---------------|---------------| +| `deploy` | A deployment has been initiated | `services`, `environments` | `service`, `environment`, `executionId` | +| `deploy_failed` | A deployment has failed | `services`, `environments` | `service`, `environment`, `executionId` | +| `canary` | A canary deployment phase has started | `services`, `environments` | `service`, `environment`, `canaryPercent` | +| `rollback` | A deployment rollback has been triggered | `services`, `environments` | `service`, `environment`, `executionId` | +| `slo_breach` | A service level objective has been breached | `services`, `slos` | `service`, `sloName`, `currentValue` | +| `post_deploy` | A deployment has completed successfully | `services`, `environments` | `service`, `environment`, `executionId` | + +### CCM events (Cloud Cost Management) + +| Event | Description | Filter fields | Event payload | +|-------|-------------|---------------|---------------| +| `cost_spike` | An unexpected cost increase detected | `resources`, `threshold-percent` | `resource`, `increasePercent`, `currentCost` | +| `budget_exceeded` | A budget threshold has been exceeded | `budgets` | `budgetName`, `budgetLimit`, `actualSpend` | +| `cost_anomaly` | A cost anomaly has been detected | `resources` | `resource`, `anomalyType`, `actualCost` | + +### STO events (Security Testing Orchestration) + +| Event | Description | Filter fields | Event payload | +|-------|-------------|---------------|---------------| +| `vulnerability_found` | A vulnerability found during a scan | `repos`, `severity`, `scan-types` | `repo`, `severity`, `component` | +| `scan_complete` | A security scan has completed | `repos`, `scan-types` | `repo`, `scanType`, `totalFindings` | +| `severity_threshold` | A severity threshold exceeded in scan results | `repos`, `scan-types` | `repo`, `threshold`, `count` | + +### Platform events + +| Event | Description | Filter fields | Event payload | +|-------|-------------|---------------|---------------| +| `comment_mention` | An agent was mentioned in a comment | `agents`, `repos` | `repo`, `pullReq`, `commentBody`, `mentionedAgent` | +| `repo_created` | A new repository has been created or imported | *(basic EventFilter)* | `repoName`, `repoNamespace` | +| `flag_stale` | A feature flag has been identified as stale | *(basic EventFilter)* | `featureFlag`, `repo`, `treatment` | +| `schedule` | Triggered on a cron schedule | *(existing ScheduleFilter)* | `scheduleName` | +| `workflow_dispatch` | Triggered manually by a user | *(existing, no filter)* | *(none)* | + +> **Note:** `schedule` and `workflow_dispatch` already exist in the spec. No new platform events needed for those — just reuse them. + +--- + +## Accessing Event Data in Pipelines + +Event payload data is available in pipeline expressions using `<+trigger.*>`: + +```yaml +# In pipeline.yaml, reference trigger/event data in inputs or env +pipeline: + on: pull_request + inputs: + repo: + type: string + default: <+trigger.repo> + pullReq: + type: string + default: <+trigger.pullReq> +``` + +Or directly in step environment variables: + +```yaml +stages: + - name: handle-failure + steps: + - name: diagnose + run: + container: + image: my-agent:1.0.0 + env: + FAILED_PIPELINE: <+trigger.executionId> + REPO: <+trigger.repo> + BRANCH: <+trigger.branch> +``` + +--- + +## Template Examples + +### autofix — triggered by CI failures + +```yaml +version: 1 +pipeline: + on: + - pipeline_failed + - build_failed + - test_failed + clone: + depth: 1 + ref: + name: <+trigger.branch> + type: branch + repo: <+trigger.repo> + stages: + - name: autofix + steps: + - name: remediation_agent + run: + container: + image: anewdocker25/mydockerhub:remediation-agent + with: + harness_execution_id: <+trigger.executionId> + working_directory: /harness + env: + ANTHROPIC_API_KEY: <+inputs.anthropicKey> + - name: coding_agent + run: + container: + image: anewdocker25/mydockerhub:coding-agent + with: + task_file_path: /harness/task.txt + working_directory: /harness + env: + ANTHROPIC_API_KEY: <+inputs.anthropicKey> + platform: + os: linux + arch: arm64 + inputs: + anthropicKey: + type: secret + default: autofix_anthropic_api_key + harnessKey: + type: secret + default: harness_api_key + gitConnector: + type: connector +``` + +**What changed:** Added `on:` stanza. Clone `ref` and `repo` now use `<+trigger.branch>` and `<+trigger.repo>` instead of `<+inputs.branch>` and `<+inputs.repo>`, so the pipeline auto-populates from the event. The `branch` and `repo` string inputs can be removed (or kept as overrides for manual runs). + +### codereview — triggered by PR events + +```yaml +version: 1 +agents: + on: + - pull_request: + types: + - opened + - synchronize + - comment_mention: + agents: + - codereview +## option 1: + inputs: + attlasianMCP: + type: connector + oneof: [attlasian] + +## option 2: +## We would need to know local and remote tools + tools: + attlasian: + type: connector + oneof: [attlasian] + read: true + write: true + + clone: + depth: 1000 + ref: + type: pull-request + number: <+trigger.pullReq> + repo: <+trigger.repo> + stages: + - name: codereview + steps: + - agent: + uses: abhinavharness/drone-ai-review-agent:1.0.0 + with: + output_file: /harness/task.txt + review_output_file: /harness/review.json + working_directory: /harness + tools: + - grep + - read + - write + - mcp + mcp_auth: ${{ tools.attlasian }} + + - name: coding_agent + run: + container: + image: anewdocker25/mydockerhub:coding-agent + with: + task_file_path: /harness/task.txt + working_directory: /harness + env: + ANTHROPIC_API_KEY: <+inputs.anthropicKey> + - name: post_comments + run: + container: + image: abhinavharness/comment-plugin:1.0.0 + with: + comments_file: /harness/review.json + repo: <+trigger.repo> + pr_number: <+trigger.pullReq> + env: + TOKEN: <+inputs.harnessKey> + platform: + os: linux + arch: arm64 + inputs: + anthropicKey: + type: secret + default: account.autofix_anthropic_api_key + harnessKey: + type: secret + default: account.harness_api_key +``` + +**What changed:** Added `on:` with `pull_request` (reusing existing GitHub-style event with `types` filter) and `comment_mention` (new Harness event with `agents` filter). Clone ref uses `<+trigger.pullReq>` and `<+trigger.repo>`. The `repo` and `pullReq` string inputs can be removed. + +### ffcleanup — triggered by stale flags or schedule + +```yaml +version: 1 +pipeline: + on: + - flag_stale + - schedule: + cron: "0 9 * * MON" + - workflow_dispatch + clone: + depth: 1 + ref: + name: <+inputs.branch> + type: branch + repo: <+trigger.repo> + stages: + - name: ffcleanup + steps: + - name: generate_task + run: + container: + image: anewdocker25/mydockerhub:coding-agent + env: + FEATURE_FLAG: <+trigger.featureFlag> + TREATMENT: <+trigger.treatment> + ANTHROPIC_API_KEY: <+inputs.anthropicKey> + platform: + os: linux + arch: arm64 + inputs: + anthropicKey: + type: secret + default: ffcleanup_anthropic_apikey + harnessApiKey: + type: secret + default: ffcleanup_harness_apikey + branch: + type: string + default: main +``` + +**What changed:** Added `on:` with `flag_stale` (new Harness event), `schedule` (existing event with cron), and `workflow_dispatch` (existing event for manual triggers). Flag data accessed via `<+trigger.featureFlag>` and `<+trigger.treatment>`. + +### onboarding — triggered when repos are created + +```yaml +version: 1 +pipeline: + on: + - repo_created + - workflow_dispatch + stages: + - name: onboarding + steps: + - name: onboarding_agent + run: + container: + image: colinharness/onboarding-agent:1.0.0 + env: + ANTHROPIC_API_KEY: <+inputs.anthropicKey> + HARNESS_API_KEY: <+inputs.harnessKey> + HARNESS_BASE_URL: <+inputs.harnessBaseURL> + REPO_NAME: <+trigger.repoName> + REPO_NAMESPACE: <+trigger.repoNamespace> + CONNECTOR_REF: <+inputs.connectorRef> + platform: + os: linux + arch: amd64 + inputs: + anthropicKey: + type: secret + required: true + harnessKey: + type: secret + required: true + harnessBaseURL: + type: secret + required: true + connectorRef: + type: string +``` + +**What changed:** Added `on:` with `repo_created` (new Harness event) and `workflow_dispatch` (manual). Repo data accessed via `<+trigger.repoName>` and `<+trigger.repoNamespace>`. + +--- + +## Progressive Complexity + +The `on:` stanza supports three levels, matching the existing spec's `On` type: + +```yaml +# 1. Simple: single event string +pipeline: + on: pull_request + +# 2. List: multiple events +pipeline: + on: + - pull_request + - pipeline_failed + - cost_spike + +# 3. Structured: events with filters +pipeline: + on: + - pull_request: + branches: + - main + - "release/**" + types: + - opened + - synchronize + - pipeline_failed: + repos: + - my-service + branches: + - main + - cost_spike: + resources: + - production-cluster + threshold-percent: 20 + - comment_mention: + agents: + - codereview + - schedule: + cron: "0 9 * * MON" + - vulnerability_found: + severity: + - critical + - high +``` + +--- + +## Compatibility + +### Existing GitHub events still work + +All current events from the spec (`push`, `pull_request`, `schedule`, `workflow_dispatch`, etc.) continue to work exactly as before. Harness events are purely additive. + +### Pipelines and agents share events + +Since `agent` is just an alias for `pipeline`, the same events work for both: + +```yaml +# A regular pipeline triggered by cost spikes +version: 1 +pipeline: + on: cost_spike + stages: + - name: alert + steps: + - name: notify + run: + shell: bash + script: echo "Cost spike detected on $RESOURCE" + env: + RESOURCE: <+trigger.resource> + +# An agent triggered by cost spikes — identical structure +version: 1 +agent: + on: cost_spike + stages: + - name: analyze + steps: + - name: cost_agent + run: + container: + image: harness/cost-analyzer:1.0.0 + env: + RESOURCE: <+trigger.resource> +``` + +### Studio compatibility + +The YAML structure is unchanged — `on` is already a valid field on `Pipeline`. Studio can render and edit agent YAMLs with triggers without any changes to the editor. + +### Manual override + +When an agent is triggered manually (via `workflow_dispatch` or API), `<+trigger.*>` fields may be empty. Templates should either: +- Keep pipeline `inputs` as fallbacks: `<+trigger.repo>` falls back to `<+inputs.repo>` if unset +- Use the `if` conditional to skip trigger-dependent logic on manual runs + +--- + +## Trigger Expression Reference + +| Expression | Description | Example value | +|------------|-------------|---------------| +| `<+trigger.event>` | The event type that fired | `pipeline_failed` | +| `<+trigger.repo>` | Repository identifier | `my-service` | +| `<+trigger.branch>` | Branch name | `main` | +| `<+trigger.pullReq>` | Pull request number | `42` | +| `<+trigger.executionId>` | Pipeline execution ID | `abc123` | +| `<+trigger.service>` | Service identifier (CD) | `payment-service` | +| `<+trigger.environment>` | Deployment environment (CD) | `production` | +| `<+trigger.resource>` | Resource identifier (CCM) | `prod-cluster` | +| `<+trigger.severity>` | Vulnerability severity (STO) | `critical` | +| `<+trigger.featureFlag>` | Feature flag identifier | `new-checkout-flow` | +| `<+trigger.repoName>` | New repo name (platform) | `my-new-repo` | +| `<+trigger.repoNamespace>` | New repo namespace (platform) | `my-org` | +| `<+trigger.mentionedAgent>` | Agent mentioned in comment | `codereview` | +| `<+trigger.commentBody>` | Comment content | `@codereview please review` | + +--- + +## Summary of All New Event Types + +| Event | Module | Use case | +|-------|--------|----------| +| `pipeline_failed` | CI | Auto-remediate broken pipelines | +| `build_failed` | CI | Fix build failures | +| `test_failed` | CI | Diagnose test failures | +| `deploy` | CD | Pre/post deployment automation | +| `deploy_failed` | CD | Rollback or remediation on deploy failure | +| `canary` | CD | Verify canary deployments | +| `rollback` | CD | Post-rollback analysis | +| `slo_breach` | CD | Respond to SLO violations | +| `post_deploy` | CD | Post-deployment verification | +| `cost_spike` | CCM | Alert and analyze cost increases | +| `budget_exceeded` | CCM | Budget overage response | +| `cost_anomaly` | CCM | Investigate cost anomalies | +| `vulnerability_found` | STO | Triage security findings | +| `scan_complete` | STO | Process scan results | +| `severity_threshold` | STO | Escalate high-severity findings | +| `comment_mention` | Platform | Respond to @agent mentions | +| `repo_created` | Platform | Auto-onboard new repositories | +| `flag_stale` | Platform | Clean up stale feature flags | + +> `schedule`, `workflow_dispatch`, `push`, `pull_request` already exist in the spec and are reused as-is. + +--- + +## Future Considerations + +- **Chained agents**: An agent completing could emit an event that triggers another (e.g., autofix completes → codereview runs on the fix PR) +- **Approval gates**: Add `approval: true` to gate trigger execution on human approval before the pipeline runs +- **Conditional execution**: Use `if: ${{ expr }}` alongside `on:` for expression-based gating +- **MCP tool setup**: Agents could declare tool/MCP dependencies as syntactic sugar in the `agent` stanza +- **Event payload expansion**: Start minimal, add fields to event payloads as real use cases demand them From 4c71344b5ebaf8e7d3567753328000975a165d72 Mon Sep 17 00:00:00 2001 From: Harshit Mahajan Date: Mon, 2 Mar 2026 18:09:12 +0530 Subject: [PATCH 2/6] init agent schema --- dist/schema.json | 261 +++++++++++++++++++++++++++++++- samples/agent-autofix.yaml | 95 ++++++++++++ samples/agent-mcp-examples.yaml | 81 ++++++++++ samples/agent-step-level.yaml | 81 ++++++++++ schema/agent.ts | 132 ++++++++++++++++ schema/schema.ts | 11 ++ schema/steps.ts | 53 +++++++ 7 files changed, 711 insertions(+), 3 deletions(-) create mode 100644 samples/agent-autofix.yaml create mode 100644 samples/agent-mcp-examples.yaml create mode 100644 samples/agent-step-level.yaml create mode 100644 schema/agent.ts diff --git a/dist/schema.json b/dist/schema.json index 6b3c387..29204bc 100644 --- a/dist/schema.json +++ b/dist/schema.json @@ -95,6 +95,142 @@ ], "type": "string" }, + "Agent": { + "description": "Agent extends Pipeline with AI agent-specific configuration. Agents are pipelines that can leverage AI capabilities including built-in tools, MCP servers, rules, and skills. This is a top-level alias for Pipeline with agent-specific fields. Use this when the entire pipeline is an AI agent workflow.", + "properties": { + "barriers": { + "description": "Barriers provides optional pipeline barriers.", + "items": { + "type": "string" + }, + "type": "array" + }, + "clone": { + "$ref": "#/definitions/Clone", + "description": "Clone overrides the default clone behavior." + }, + "concurrency": { + "$ref": "#/definitions/Concurrency", + "description": "Concurrency groups provide a way to limit concurrency execution of pipelines that share the same concurrency key." + }, + "default": {}, + "delegate": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "description": "Delegage defines the default delegate that should handle stage execution. This is optional." + }, + "env": { + "additionalProperties": { + "type": "string" + }, + "description": "Env provides global environment variables that propagate to all pipeline steps.", + "type": "object" + }, + "environment": { + "$ref": "#/definitions/EnvironmentRef", + "description": "Environment defines the target deployment environment (e.g. development, prod)." + }, + "generate": { + "$ref": "#/definitions/Stage", + "description": "Generate defines custom logic to dynamically generate a pipeline." + }, + "id": { + "deprecated": true, + "description": "Id provides a unique pipeline identifer.", + "type": "string" + }, + "if": { + "description": "If provides conditional pipeline execution logic. If the condition resolves to false, the pipeline is skipped.", + "type": "string" + }, + "inputs": { + "additionalProperties": { + "$ref": "#/definitions/Input" + }, + "description": "Inputs provides pipeline input variables.", + "type": "object" + }, + "jobs": { + "additionalProperties": { + "$ref": "#/definitions/Stage" + }, + "description": "Jobs defines jobs (stages) in the pipeline.\n\nThis property is available solely for the purpose of backward compatibility with GitHub Actions.", + "type": "object" + }, + "mcp_servers": { + "additionalProperties": { + "$ref": "#/definitions/McpServer" + }, + "description": "McpServers defines Model Context Protocol servers available to all agent steps. Step-level mcp_servers configuration will be merged with this.", + "type": "object" + }, + "name": { + "deprecated": true, + "description": "Name provides a pipeline name.", + "type": "string" + }, + "on": { + "$ref": "#/definitions/On", + "description": "On provides condition pipeline execution logic based on trigger event and action mapping. If the conditional logic resolves to folse, the pipeline is skipped." + }, + "permissions": { + "$ref": "#/definitions/Permissions" + }, + "repo": { + "$ref": "#/definitions/Repository", + "description": "Repo overrides the default repository." + }, + "rules": { + "description": "Rules defines behavioral constraints for the agent. Can be file paths (e.g., \"./agents.md\") or inline rule text. Validation engine determines if value is a path or inline content.", + "items": { + "type": "string" + }, + "type": "array" + }, + "service": { + "$ref": "#/definitions/ServiceRef", + "description": "Service defines the service being deployed." + }, + "skills": { + "description": "Skills defines skill files (markdown instructions) for the agent. Can be file paths or inline content.", + "items": { + "type": "string" + }, + "type": "array" + }, + "stages": { + "description": "Stages provides a list of stages. Each pipeline is made up of one or more stages that executes sequentially.", + "items": { + "$ref": "#/definitions/Stage" + }, + "type": "array" + }, + "status": { + "$ref": "#/definitions/Status", + "description": "Status overrides the default status behavior." + }, + "timeout": { + "description": "Timeout defines the step timeout duration.", + "format": "duration", + "type": "string" + }, + "tools": { + "$ref": "#/definitions/Tools", + "description": "Tools configures built-in tools available to all agent steps. Step-level tools configuration will be merged with this." + } + }, + "type": "object", + "x-go-file": "agent.go" + }, "Cache": { "description": "Cache defines pipeline caching behavior.", "properties": { @@ -514,7 +650,7 @@ }, "type": "array" }, - "parallel": { + "sequential": { "type": "boolean" } }, @@ -698,6 +834,19 @@ "type": "array" } ] + }, + "exitcode": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ] } }, "type": "object" @@ -818,7 +967,9 @@ "duration", "choice", "environment", - "secret" + "secret", + "step", + "object" ], "type": "string" } @@ -869,6 +1020,57 @@ "type": "object", "x-go-file": "strategy_matrix.go" }, + "McpServer": { + "description": "McpServer defines a Model Context Protocol server configuration. Supports multiple transport types: stdio (command), container (docker), HTTP (url), and registry-based servers.", + "properties": { + "allowed": { + "description": "Allowed specifies which tools from this MCP server are available. Use [\"*\"] to allow all tools, or list specific tool names.", + "items": { + "type": "string" + }, + "type": "array" + }, + "args": { + "description": "Args specifies command arguments for stdio-based MCP servers.", + "items": { + "type": "string" + }, + "type": "array" + }, + "command": { + "description": "Command specifies the command to run for stdio-based MCP servers. Used with args for process-based servers (e.g., \"npx\", \"uvx\").", + "type": "string" + }, + "container": { + "description": "Container specifies a Docker image for container-based MCP servers. The container is run with stdin/stdout communication.", + "type": "string" + }, + "env": { + "additionalProperties": { + "type": "string" + }, + "description": "Env specifies environment variables passed to the MCP server.", + "type": "object" + }, + "headers": { + "additionalProperties": { + "type": "string" + }, + "description": "Headers specifies HTTP headers for authentication with remote MCP servers. Commonly used for Bearer tokens or API keys.", + "type": "object" + }, + "registry": { + "description": "Registry specifies a reference to an MCP server in a registry. Used for discovery and version management.", + "type": "string" + }, + "url": { + "description": "Url specifies the HTTP endpoint for remote MCP servers. Must implement the MCP specification over HTTP.", + "type": "string" + } + }, + "type": "object", + "x-go-file": "mcp_server.go" + }, "Mount": { "anyOf": [ { @@ -1492,6 +1694,10 @@ "deprecated": "use \"template\" instead", "description": "Action defines re-usable pipeline steps and stages." }, + "agent": { + "$ref": "#/definitions/Agent", + "description": "Agent defines an AI agent pipeline configuration. Agents are pipelines with AI-specific capabilities including tools, MCP servers, rules, and skills.\n\nThis is a top-level alias for Pipeline with agent-specific fields. Mutually exclusive with pipeline at runtime." + }, "concurrency": { "$ref": "#/definitions/Concurrency", "description": "Concurrency groups provide a way to limit concurrency execution of pipelines that share the same concurrency key." @@ -1610,7 +1816,7 @@ }, "type": "array" }, - "parallel": { + "sequential": { "type": "boolean" } }, @@ -1629,6 +1835,10 @@ "$ref": "#/definitions/Cache", "description": "Cache defines the cache configuration." }, + "chain": { + "$ref": "#/definitions/StageChain", + "description": "Chain defines a chained pipeline." + }, "clone": { "$ref": "#/definitions/Clone", "description": "Clone overrides the default clone settings." @@ -1787,6 +1997,18 @@ "type": "object", "x-go-file": "stage_approval.go" }, + "StageChain": { + "properties": { + "uses": { + "type": "string" + }, + "with": { + "type": "object" + } + }, + "type": "object", + "x-go-file": "stage_template.go" + }, "StageGroup": { "properties": { "parallel": { @@ -2351,6 +2573,39 @@ }, "type": "object" }, + "Tools": { + "description": "Tools configures built-in tools available to the agent.", + "properties": { + "bash": { + "anyOf": [ + { + "type": "boolean" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "description": "Bash configures shell command execution.\n- true: enables default safe commands\n- false: disables bash\n- string[]: list of allowed commands (e.g., [\"echo\", \"ls\", \"git:*\"])" + }, + "grep": { + "description": "Grep enables grep/search capability.", + "type": "boolean" + }, + "read": { + "description": "Read enables file read capability.", + "type": "boolean" + }, + "write": { + "description": "Write enables file write capability.", + "type": "boolean" + } + }, + "type": "object", + "x-go-file": "tools.go" + }, "Volume": { "properties": { "name": { diff --git a/samples/agent-autofix.yaml b/samples/agent-autofix.yaml new file mode 100644 index 0000000..b1c6259 --- /dev/null +++ b/samples/agent-autofix.yaml @@ -0,0 +1,95 @@ +# Autofix Agent - Pipeline-level agent example +# Demonstrates tools, mcp_servers, rules, and skills at pipeline level + +version: 1 +agent: + # Built-in tools available to all agent steps + tools: + read: true + write: true + grep: true + bash: + - "git:*" + - "npm:*" + - "echo" + - "cat" + + # MCP servers available to all agent steps + mcp_servers: + slack: + container: mcp/slack:latest + env: + SLACK_BOT_TOKEN: <+secrets.getValue("slack_bot_token")> + allowed: + - send_message + - get_channel_history + + # Behavioral rules (file paths or inline) + rules: + - ./agents.md + - "Never modify files outside the repository root" + - "Always run tests before committing changes" + + # Skill files + skills: + - ./skills/coding.md + - ./skills/debugging.md + + clone: + depth: 1 + ref: + name: <+inputs.branch> + type: branch + repo: <+inputs.repo> + + stages: + - name: autofix + steps: + - name: remediation_agent + run: + container: + image: harness/remediation-agent:1.0.0 + with: + detailed_logging: "true" + harness_api_key: <+inputs.harnessKey> + output_dir: /harness/autofix + working_directory: /harness + harness_execution_id: <+inputs.executionId> + env: + ANTHROPIC_API_KEY: <+inputs.llmConnector.token> + + - name: coding_agent + run: + container: + image: harness/coding-agent:1.0.0 + with: + detailed_logging: "true" + max_iterations: "50" + task_file_path: /harness/autofix/task.txt + working_directory: /harness + env: + ANTHROPIC_API_KEY: <+inputs.llmConnector.token> + + - name: show_git_diff + run: + shell: bash + script: |- + git add -A + git diff --cached + + inputs: + repo: + type: string + description: Repository to clone + branch: + type: string + description: Branch to checkout + executionId: + type: string + description: Harness execution ID for context + harnessKey: + type: secret + description: Harness API key + llmConnector: + type: connector + description: LLM connector with API token diff --git a/samples/agent-mcp-examples.yaml b/samples/agent-mcp-examples.yaml new file mode 100644 index 0000000..84d2369 --- /dev/null +++ b/samples/agent-mcp-examples.yaml @@ -0,0 +1,81 @@ +# MCP Server Configuration Examples +# Demonstrates all 4 MCP transport types: stdio, container, HTTP, registry + +version: 1 +agent: + tools: + read: true + write: true + bash: true + + mcp_servers: + # 1. Stdio MCP Server (command + args) + # Runs a local process with stdin/stdout communication + serena: + command: "uvx" + args: ["--from", "git+https://github.com/oraios/serena", "serena"] + allowed: ["*"] + + # 2. Container MCP Server (Docker image) + # Runs in an isolated container + ast-grep: + container: mcp/ast-grep:latest + allowed: ["*"] + + notion: + container: mcp/notion:latest + env: + NOTION_TOKEN: <+secrets.getValue("notion_token")> + allowed: + - search_pages + - get_page + - get_database + - query_database + + # 3. HTTP MCP Server (remote endpoint) + # Connects to a remote MCP server via HTTP + microsoftdocs: + url: https://learn.microsoft.com/api/mcp + allowed: ["*"] + + deepwiki: + url: https://mcp.deepwiki.com/sse + allowed: + - read_wiki_structure + - read_wiki_contents + - ask_question + + authenticated-api: + url: https://api.example.com/mcp + headers: + Authorization: "Bearer <+secrets.getValue("api_token")>" + X-Custom-Header: "custom-value" + allowed: ["*"] + + # 4. Registry-based MCP Server + # References server from MCP registry for discovery/versioning + markitdown: + registry: https://api.mcp.github.com/v0/servers/microsoft/markitdown + container: ghcr.io/microsoft/markitdown + allowed: ["*"] + + filesystem: + registry: https://api.mcp.github.com/v0/servers/modelcontextprotocol/filesystem + command: "npx" + args: ["-y", "@modelcontextprotocol/server-filesystem"] + allowed: + - read_file + - write_file + - list_directory + + stages: + - name: demo + steps: + - name: mcp_demo_agent + run: + container: + image: harness/coding-agent:1.0.0 + with: + task: "Demonstrate MCP server usage" + env: + ANTHROPIC_API_KEY: <+inputs.llmConnector.token> diff --git a/samples/agent-step-level.yaml b/samples/agent-step-level.yaml new file mode 100644 index 0000000..9d68721 --- /dev/null +++ b/samples/agent-step-level.yaml @@ -0,0 +1,81 @@ +# Step-level Agent Example +# Demonstrates StepAgent with tools, mcp_servers, rules, skills at step level +# Step-level config merges with pipeline-level config + +version: 1 +pipeline: + clone: + depth: 1 + repo: <+inputs.repo> + + stages: + - name: code-review + steps: + # Regular run step (not an agent) + - name: setup + run: + shell: bash + script: | + echo "Setting up environment..." + npm install + + # Agent step with step-level configuration + # This extends StepLong - only `run` step type is valid + # tools, mcp_servers, rules, skills are agent-specific fields + - name: code_review_agent + run: + container: + image: harness/code-review-agent:1.0.0 + with: + pr_number: <+inputs.prNumber> + review_type: "comprehensive" + env: + ANTHROPIC_API_KEY: <+inputs.llmConnector.token> + # Agent-specific fields at step level + tools: + read: true + write: false # Read-only for code review + grep: true + bash: + - "git diff" + - "git log" + mcp_servers: + github: + url: https://api.github.com/mcp + headers: + Authorization: "Bearer <+inputs.githubToken>" + allowed: + - get_pull_request + - list_comments + - create_review + jira: + container: mcp/jira:latest + env: + JIRA_API_TOKEN: <+secrets.getValue("jira_token")> + allowed: + - get_issue + - add_comment + rules: + - "Focus on code quality and best practices" + - "Do not approve PRs with security vulnerabilities" + skills: + - ./skills/code-review.md + max_turns: 25 + task: "Review the pull request and provide detailed feedback" + + # Another regular step after the agent + - name: post-review + run: + shell: bash + script: | + echo "Code review completed" + + inputs: + repo: + type: string + prNumber: + type: number + githubToken: + type: secret + llmConnector: + type: connector diff --git a/schema/agent.ts b/schema/agent.ts new file mode 100644 index 0000000..7991b8a --- /dev/null +++ b/schema/agent.ts @@ -0,0 +1,132 @@ +import { Pipeline } from "./pipeline"; + +// +// Built-in Tools Configuration +// + +/** + * Tools configures built-in tools available to the agent. + * @x-go-file tools.go + */ +export interface Tools { + /** + * Read enables file read capability. + */ + read?: boolean; + + /** + * Write enables file write capability. + */ + write?: boolean; + + /** + * Grep enables grep/search capability. + */ + grep?: boolean; + + /** + * Bash configures shell command execution. + * - true: enables default safe commands + * - false: disables bash + * - string[]: list of allowed commands (e.g., ["echo", "ls", "git:*"]) + */ + bash?: boolean | string[]; +} + +// +// MCP Server Configuration +// + +/** + * McpServer defines a Model Context Protocol server configuration. + * Supports multiple transport types: stdio (command), container (docker), + * HTTP (url), and registry-based servers. + * @x-go-file mcp_server.go + */ +export interface McpServer { + /** + * Command specifies the command to run for stdio-based MCP servers. + * Used with args for process-based servers (e.g., "npx", "uvx"). + */ + command?: string; + + /** + * Args specifies command arguments for stdio-based MCP servers. + */ + args?: string[]; + + /** + * Container specifies a Docker image for container-based MCP servers. + * The container is run with stdin/stdout communication. + */ + container?: string; + + /** + * Url specifies the HTTP endpoint for remote MCP servers. + * Must implement the MCP specification over HTTP. + */ + url?: string; + + /** + * Headers specifies HTTP headers for authentication with remote MCP servers. + * Commonly used for Bearer tokens or API keys. + */ + headers?: Record; + + /** + * Registry specifies a reference to an MCP server in a registry. + * Used for discovery and version management. + */ + registry?: string; + + /** + * Env specifies environment variables passed to the MCP server. + */ + env?: Record; + + /** + * Allowed specifies which tools from this MCP server are available. + * Use ["*"] to allow all tools, or list specific tool names. + */ + allowed?: string[]; +} + +// +// Agent Interface (Pipeline-Level) +// + +/** + * Agent extends Pipeline with AI agent-specific configuration. Agents are pipelines that can leverage AI capabilities including built-in tools, MCP servers, rules, and skills. This is a top-level alias for Pipeline with agent-specific fields. Use this when the entire pipeline is an AI agent workflow. + * @x-go-file agent.go + */ +export interface Agent extends Pipeline { + /** + * Tools configures built-in tools available to all agent steps. + * Step-level tools configuration will be merged with this. + */ + tools?: Tools; + + /** + * McpServers defines Model Context Protocol servers available to all agent steps. + * Step-level mcp_servers configuration will be merged with this. + */ + mcp_servers?: Record; + + /** + * Rules defines behavioral constraints for the agent. + * Can be file paths (e.g., "./agents.md") or inline rule text. + * Validation engine determines if value is a path or inline content. + */ + rules?: string[]; + + /** + * Skills defines skill files (markdown instructions) for the agent. + * Can be file paths or inline content. + */ + skills?: string[]; + + // TODO: Engine selection - needs abstraction for harness-coding-agent and claude-code + // to support multiple AI models with similar interfaces. + // + // engine?: "harness-coding-agent" | "claude-code"; +} diff --git a/schema/schema.ts b/schema/schema.ts index 1e3a45f..8edde9d 100644 --- a/schema/schema.ts +++ b/schema/schema.ts @@ -1,3 +1,4 @@ +import { Agent } from "./agent"; import { Concurrency } from "./concurrency"; import { Environment } from "./environment"; import { Permissions } from "./permissions"; @@ -21,6 +22,16 @@ export interface Schema { */ pipeline?: Pipeline; + /** + * Agent defines an AI agent pipeline configuration. + * Agents are pipelines with AI-specific capabilities including + * tools, MCP servers, rules, and skills. + * + * This is a top-level alias for Pipeline with agent-specific fields. + * Mutually exclusive with pipeline at runtime. + */ + agent?: Agent; + /** * Environment defines a deployment environment. */ diff --git a/schema/steps.ts b/schema/steps.ts index eb46e28..407b4b4 100644 --- a/schema/steps.ts +++ b/schema/steps.ts @@ -1,3 +1,4 @@ +import {Tools, McpServer} from "./agent"; import {Container} from "./container"; import {CloneRef} from "./clone"; import {FailureStrategy} from "./failure"; @@ -470,3 +471,55 @@ export interface TestIntelligence { // export type Delegate = "inherit-from-infrastrcuture" | string | string[]; + +// +// StepAgent (Step-Level Agent) +// + +/** + * StepAgent extends StepLong with AI agent-specific configuration. + * + * IMPORTANT: Only the `run` step type is supported for agent steps. + * Other step types (action, template, clone, etc.) inherited from StepLong + * should be rejected at runtime validation. + * + * Agent-specific fields (tools, mcp_servers, rules, skills) at step level + * are merged with pipeline-level Agent configuration using merge strategy. + * + * @x-go-file step_agent.go + */ +export interface StepAgent extends StepLong { + /** + * Tools configures built-in tools for this agent step. + * Merged with pipeline-level tools configuration. + */ + tools?: Tools; + + /** + * McpServers defines MCP servers for this agent step. + * Merged with pipeline-level mcp_servers configuration. + */ + mcp_servers?: Record; + + /** + * Rules defines behavioral constraints for this agent step. + * Merged with pipeline-level rules. + */ + rules?: string[]; + + /** + * Skills defines skill files for this agent step. + * Merged with pipeline-level skills. + */ + skills?: string[]; + + /** + * MaxTurns defines the maximum number of agentic turns before forced stop. + */ + max_turns?: number; + + /** + * Task defines the task prompt or path to a task file. + */ + task?: string; +} From dc9fdbe811e8c8ab06bd9db214007400f046ac76 Mon Sep 17 00:00:00 2001 From: Harshit Mahajan Date: Mon, 2 Mar 2026 18:34:35 +0530 Subject: [PATCH 3/6] add step agent --- samples/agent-autofix.yaml | 4 ++-- samples/agent-mcp-examples.yaml | 2 +- samples/agent-step-level.yaml | 4 +--- schema/steps.ts | 32 ++++++++++++++++++++++---------- 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/samples/agent-autofix.yaml b/samples/agent-autofix.yaml index b1c6259..9a0eb02 100644 --- a/samples/agent-autofix.yaml +++ b/samples/agent-autofix.yaml @@ -46,7 +46,7 @@ agent: - name: autofix steps: - name: remediation_agent - run: + agent: container: image: harness/remediation-agent:1.0.0 with: @@ -59,7 +59,7 @@ agent: ANTHROPIC_API_KEY: <+inputs.llmConnector.token> - name: coding_agent - run: + agent: container: image: harness/coding-agent:1.0.0 with: diff --git a/samples/agent-mcp-examples.yaml b/samples/agent-mcp-examples.yaml index 84d2369..dbe945f 100644 --- a/samples/agent-mcp-examples.yaml +++ b/samples/agent-mcp-examples.yaml @@ -72,7 +72,7 @@ agent: - name: demo steps: - name: mcp_demo_agent - run: + agent: container: image: harness/coding-agent:1.0.0 with: diff --git a/samples/agent-step-level.yaml b/samples/agent-step-level.yaml index 9d68721..78a5816 100644 --- a/samples/agent-step-level.yaml +++ b/samples/agent-step-level.yaml @@ -20,10 +20,8 @@ pipeline: npm install # Agent step with step-level configuration - # This extends StepLong - only `run` step type is valid - # tools, mcp_servers, rules, skills are agent-specific fields - name: code_review_agent - run: + agent: container: image: harness/code-review-agent:1.0.0 with: diff --git a/schema/steps.ts b/schema/steps.ts index 407b4b4..a7c408c 100644 --- a/schema/steps.ts +++ b/schema/steps.ts @@ -38,6 +38,11 @@ export interface StepLong { */ run?: string | StepRun; + /** + * Agent defines an agent step. + */ + agent?: string | StepAgent; + /** * Test defines a run test step */ @@ -477,18 +482,25 @@ export type Delegate = "inherit-from-infrastrcuture" | string | string[]; // /** - * StepAgent extends StepLong with AI agent-specific configuration. - * - * IMPORTANT: Only the `run` step type is supported for agent steps. - * Other step types (action, template, clone, etc.) inherited from StepLong - * should be rejected at runtime validation. - * - * Agent-specific fields (tools, mcp_servers, rules, skills) at step level - * are merged with pipeline-level Agent configuration using merge strategy. - * + * StepAgent defines an AI agent step configuration. Agent-specific fields (tools, mcp_servers, rules, skills) at step level are merged with pipeline-level Agent configuration using merge strategy. * @x-go-file step_agent.go */ -export interface StepAgent extends StepLong { +export interface StepAgent { + /** + * Container runs the agent inside a container. + */ + container?: Container; + + /** + * Env defines the environment variables for the agent. + */ + env?: Record; + + /** + * With defines configuration parameters passed to the agent. + */ + with?: Record; + /** * Tools configures built-in tools for this agent step. * Merged with pipeline-level tools configuration. From 60760d01360d78cd3ead7a6b7d3156668fec7f6b Mon Sep 17 00:00:00 2001 From: Harshit Mahajan Date: Mon, 2 Mar 2026 18:35:47 +0530 Subject: [PATCH 4/6] update dist --- dist/schema.json | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/dist/schema.json b/dist/schema.json index 29204bc..57e86f5 100644 --- a/dist/schema.json +++ b/dist/schema.json @@ -2105,6 +2105,61 @@ "type": "object", "x-go-file": "step_action.go" }, + "StepAgent": { + "description": "StepAgent defines an AI agent step configuration. Agent-specific fields (tools, mcp_servers, rules, skills) at step level are merged with pipeline-level Agent configuration using merge strategy.", + "properties": { + "container": { + "$ref": "#/definitions/Container", + "description": "Container runs the agent inside a container." + }, + "env": { + "additionalProperties": { + "type": "string" + }, + "description": "Env defines the environment variables for the agent.", + "type": "object" + }, + "max_turns": { + "description": "MaxTurns defines the maximum number of agentic turns before forced stop.", + "type": "number" + }, + "mcp_servers": { + "additionalProperties": { + "$ref": "#/definitions/McpServer" + }, + "description": "McpServers defines MCP servers for this agent step. Merged with pipeline-level mcp_servers configuration.", + "type": "object" + }, + "rules": { + "description": "Rules defines behavioral constraints for this agent step. Merged with pipeline-level rules.", + "items": { + "type": "string" + }, + "type": "array" + }, + "skills": { + "description": "Skills defines skill files for this agent step. Merged with pipeline-level skills.", + "items": { + "type": "string" + }, + "type": "array" + }, + "task": { + "description": "Task defines the task prompt or path to a task file.", + "type": "string" + }, + "tools": { + "$ref": "#/definitions/Tools", + "description": "Tools configures built-in tools for this agent step. Merged with pipeline-level tools configuration." + }, + "with": { + "description": "With defines configuration parameters passed to the agent.", + "type": "object" + } + }, + "type": "object", + "x-go-file": "step_agent.go" + }, "StepApproval": { "properties": { "env": { @@ -2239,6 +2294,17 @@ "$ref": "#/definitions/StepAction", "description": "Action defines an action step." }, + "agent": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/StepAgent" + } + ], + "description": "Agent defines an agent step." + }, "approval": { "$ref": "#/definitions/StepApproval", "description": "Approval defines an approval step." From 047a6f968a5a8fd77f26a4665281e3aec2b7b730 Mon Sep 17 00:00:00 2001 From: Harshit Mahajan Date: Mon, 2 Mar 2026 18:40:34 +0530 Subject: [PATCH 5/6] revert dist changes for now --- dist/schema.json | 327 +---------------------------------------------- 1 file changed, 3 insertions(+), 324 deletions(-) diff --git a/dist/schema.json b/dist/schema.json index 57e86f5..6b3c387 100644 --- a/dist/schema.json +++ b/dist/schema.json @@ -95,142 +95,6 @@ ], "type": "string" }, - "Agent": { - "description": "Agent extends Pipeline with AI agent-specific configuration. Agents are pipelines that can leverage AI capabilities including built-in tools, MCP servers, rules, and skills. This is a top-level alias for Pipeline with agent-specific fields. Use this when the entire pipeline is an AI agent workflow.", - "properties": { - "barriers": { - "description": "Barriers provides optional pipeline barriers.", - "items": { - "type": "string" - }, - "type": "array" - }, - "clone": { - "$ref": "#/definitions/Clone", - "description": "Clone overrides the default clone behavior." - }, - "concurrency": { - "$ref": "#/definitions/Concurrency", - "description": "Concurrency groups provide a way to limit concurrency execution of pipelines that share the same concurrency key." - }, - "default": {}, - "delegate": { - "anyOf": [ - { - "type": "string" - }, - { - "items": { - "type": "string" - }, - "type": "array" - } - ], - "description": "Delegage defines the default delegate that should handle stage execution. This is optional." - }, - "env": { - "additionalProperties": { - "type": "string" - }, - "description": "Env provides global environment variables that propagate to all pipeline steps.", - "type": "object" - }, - "environment": { - "$ref": "#/definitions/EnvironmentRef", - "description": "Environment defines the target deployment environment (e.g. development, prod)." - }, - "generate": { - "$ref": "#/definitions/Stage", - "description": "Generate defines custom logic to dynamically generate a pipeline." - }, - "id": { - "deprecated": true, - "description": "Id provides a unique pipeline identifer.", - "type": "string" - }, - "if": { - "description": "If provides conditional pipeline execution logic. If the condition resolves to false, the pipeline is skipped.", - "type": "string" - }, - "inputs": { - "additionalProperties": { - "$ref": "#/definitions/Input" - }, - "description": "Inputs provides pipeline input variables.", - "type": "object" - }, - "jobs": { - "additionalProperties": { - "$ref": "#/definitions/Stage" - }, - "description": "Jobs defines jobs (stages) in the pipeline.\n\nThis property is available solely for the purpose of backward compatibility with GitHub Actions.", - "type": "object" - }, - "mcp_servers": { - "additionalProperties": { - "$ref": "#/definitions/McpServer" - }, - "description": "McpServers defines Model Context Protocol servers available to all agent steps. Step-level mcp_servers configuration will be merged with this.", - "type": "object" - }, - "name": { - "deprecated": true, - "description": "Name provides a pipeline name.", - "type": "string" - }, - "on": { - "$ref": "#/definitions/On", - "description": "On provides condition pipeline execution logic based on trigger event and action mapping. If the conditional logic resolves to folse, the pipeline is skipped." - }, - "permissions": { - "$ref": "#/definitions/Permissions" - }, - "repo": { - "$ref": "#/definitions/Repository", - "description": "Repo overrides the default repository." - }, - "rules": { - "description": "Rules defines behavioral constraints for the agent. Can be file paths (e.g., \"./agents.md\") or inline rule text. Validation engine determines if value is a path or inline content.", - "items": { - "type": "string" - }, - "type": "array" - }, - "service": { - "$ref": "#/definitions/ServiceRef", - "description": "Service defines the service being deployed." - }, - "skills": { - "description": "Skills defines skill files (markdown instructions) for the agent. Can be file paths or inline content.", - "items": { - "type": "string" - }, - "type": "array" - }, - "stages": { - "description": "Stages provides a list of stages. Each pipeline is made up of one or more stages that executes sequentially.", - "items": { - "$ref": "#/definitions/Stage" - }, - "type": "array" - }, - "status": { - "$ref": "#/definitions/Status", - "description": "Status overrides the default status behavior." - }, - "timeout": { - "description": "Timeout defines the step timeout duration.", - "format": "duration", - "type": "string" - }, - "tools": { - "$ref": "#/definitions/Tools", - "description": "Tools configures built-in tools available to all agent steps. Step-level tools configuration will be merged with this." - } - }, - "type": "object", - "x-go-file": "agent.go" - }, "Cache": { "description": "Cache defines pipeline caching behavior.", "properties": { @@ -650,7 +514,7 @@ }, "type": "array" }, - "sequential": { + "parallel": { "type": "boolean" } }, @@ -834,19 +698,6 @@ "type": "array" } ] - }, - "exitcode": { - "anyOf": [ - { - "type": "string" - }, - { - "items": { - "type": "string" - }, - "type": "array" - } - ] } }, "type": "object" @@ -967,9 +818,7 @@ "duration", "choice", "environment", - "secret", - "step", - "object" + "secret" ], "type": "string" } @@ -1020,57 +869,6 @@ "type": "object", "x-go-file": "strategy_matrix.go" }, - "McpServer": { - "description": "McpServer defines a Model Context Protocol server configuration. Supports multiple transport types: stdio (command), container (docker), HTTP (url), and registry-based servers.", - "properties": { - "allowed": { - "description": "Allowed specifies which tools from this MCP server are available. Use [\"*\"] to allow all tools, or list specific tool names.", - "items": { - "type": "string" - }, - "type": "array" - }, - "args": { - "description": "Args specifies command arguments for stdio-based MCP servers.", - "items": { - "type": "string" - }, - "type": "array" - }, - "command": { - "description": "Command specifies the command to run for stdio-based MCP servers. Used with args for process-based servers (e.g., \"npx\", \"uvx\").", - "type": "string" - }, - "container": { - "description": "Container specifies a Docker image for container-based MCP servers. The container is run with stdin/stdout communication.", - "type": "string" - }, - "env": { - "additionalProperties": { - "type": "string" - }, - "description": "Env specifies environment variables passed to the MCP server.", - "type": "object" - }, - "headers": { - "additionalProperties": { - "type": "string" - }, - "description": "Headers specifies HTTP headers for authentication with remote MCP servers. Commonly used for Bearer tokens or API keys.", - "type": "object" - }, - "registry": { - "description": "Registry specifies a reference to an MCP server in a registry. Used for discovery and version management.", - "type": "string" - }, - "url": { - "description": "Url specifies the HTTP endpoint for remote MCP servers. Must implement the MCP specification over HTTP.", - "type": "string" - } - }, - "type": "object", - "x-go-file": "mcp_server.go" - }, "Mount": { "anyOf": [ { @@ -1694,10 +1492,6 @@ "deprecated": "use \"template\" instead", "description": "Action defines re-usable pipeline steps and stages." }, - "agent": { - "$ref": "#/definitions/Agent", - "description": "Agent defines an AI agent pipeline configuration. Agents are pipelines with AI-specific capabilities including tools, MCP servers, rules, and skills.\n\nThis is a top-level alias for Pipeline with agent-specific fields. Mutually exclusive with pipeline at runtime." - }, "concurrency": { "$ref": "#/definitions/Concurrency", "description": "Concurrency groups provide a way to limit concurrency execution of pipelines that share the same concurrency key." @@ -1816,7 +1610,7 @@ }, "type": "array" }, - "sequential": { + "parallel": { "type": "boolean" } }, @@ -1835,10 +1629,6 @@ "$ref": "#/definitions/Cache", "description": "Cache defines the cache configuration." }, - "chain": { - "$ref": "#/definitions/StageChain", - "description": "Chain defines a chained pipeline." - }, "clone": { "$ref": "#/definitions/Clone", "description": "Clone overrides the default clone settings." @@ -1997,18 +1787,6 @@ "type": "object", "x-go-file": "stage_approval.go" }, - "StageChain": { - "properties": { - "uses": { - "type": "string" - }, - "with": { - "type": "object" - } - }, - "type": "object", - "x-go-file": "stage_template.go" - }, "StageGroup": { "properties": { "parallel": { @@ -2105,61 +1883,6 @@ "type": "object", "x-go-file": "step_action.go" }, - "StepAgent": { - "description": "StepAgent defines an AI agent step configuration. Agent-specific fields (tools, mcp_servers, rules, skills) at step level are merged with pipeline-level Agent configuration using merge strategy.", - "properties": { - "container": { - "$ref": "#/definitions/Container", - "description": "Container runs the agent inside a container." - }, - "env": { - "additionalProperties": { - "type": "string" - }, - "description": "Env defines the environment variables for the agent.", - "type": "object" - }, - "max_turns": { - "description": "MaxTurns defines the maximum number of agentic turns before forced stop.", - "type": "number" - }, - "mcp_servers": { - "additionalProperties": { - "$ref": "#/definitions/McpServer" - }, - "description": "McpServers defines MCP servers for this agent step. Merged with pipeline-level mcp_servers configuration.", - "type": "object" - }, - "rules": { - "description": "Rules defines behavioral constraints for this agent step. Merged with pipeline-level rules.", - "items": { - "type": "string" - }, - "type": "array" - }, - "skills": { - "description": "Skills defines skill files for this agent step. Merged with pipeline-level skills.", - "items": { - "type": "string" - }, - "type": "array" - }, - "task": { - "description": "Task defines the task prompt or path to a task file.", - "type": "string" - }, - "tools": { - "$ref": "#/definitions/Tools", - "description": "Tools configures built-in tools for this agent step. Merged with pipeline-level tools configuration." - }, - "with": { - "description": "With defines configuration parameters passed to the agent.", - "type": "object" - } - }, - "type": "object", - "x-go-file": "step_agent.go" - }, "StepApproval": { "properties": { "env": { @@ -2294,17 +2017,6 @@ "$ref": "#/definitions/StepAction", "description": "Action defines an action step." }, - "agent": { - "anyOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/StepAgent" - } - ], - "description": "Agent defines an agent step." - }, "approval": { "$ref": "#/definitions/StepApproval", "description": "Approval defines an approval step." @@ -2639,39 +2351,6 @@ }, "type": "object" }, - "Tools": { - "description": "Tools configures built-in tools available to the agent.", - "properties": { - "bash": { - "anyOf": [ - { - "type": "boolean" - }, - { - "items": { - "type": "string" - }, - "type": "array" - } - ], - "description": "Bash configures shell command execution.\n- true: enables default safe commands\n- false: disables bash\n- string[]: list of allowed commands (e.g., [\"echo\", \"ls\", \"git:*\"])" - }, - "grep": { - "description": "Grep enables grep/search capability.", - "type": "boolean" - }, - "read": { - "description": "Read enables file read capability.", - "type": "boolean" - }, - "write": { - "description": "Write enables file write capability.", - "type": "boolean" - } - }, - "type": "object", - "x-go-file": "tools.go" - }, "Volume": { "properties": { "name": { From 8d3484886884603e8769a5ba62a396afa3175d16 Mon Sep 17 00:00:00 2001 From: Rohan Gupta Date: Tue, 3 Mar 2026 17:18:14 -0800 Subject: [PATCH 6/6] Brad Feedback changes --- samples/agent-autofix.yaml | 19 +++------- samples/agent-mcp-examples.yaml | 7 +--- samples/agent-step-level.yaml | 11 +----- schema/agent.ts | 65 +++++++++------------------------ schema/steps.ts | 18 ++++----- 5 files changed, 33 insertions(+), 87 deletions(-) diff --git a/samples/agent-autofix.yaml b/samples/agent-autofix.yaml index 9a0eb02..8a84d8d 100644 --- a/samples/agent-autofix.yaml +++ b/samples/agent-autofix.yaml @@ -1,21 +1,10 @@ # Autofix Agent - Pipeline-level agent example -# Demonstrates tools, mcp_servers, rules, and skills at pipeline level +# Demonstrates mcp, rules, and skills at pipeline level version: 1 agent: - # Built-in tools available to all agent steps - tools: - read: true - write: true - grep: true - bash: - - "git:*" - - "npm:*" - - "echo" - - "cat" - # MCP servers available to all agent steps - mcp_servers: + mcp: slack: container: mcp/slack:latest env: @@ -24,11 +13,13 @@ agent: - send_message - get_channel_history - # Behavioral rules (file paths or inline) + # Behavioral rules (file paths, inline, or entity references) rules: - ./agents.md - "Never modify files outside the repository root" - "Always run tests before committing changes" + - account.golang # read rules from account-level entity + - project.* # read all rules from project-level entities # Skill files skills: diff --git a/samples/agent-mcp-examples.yaml b/samples/agent-mcp-examples.yaml index dbe945f..f5e010d 100644 --- a/samples/agent-mcp-examples.yaml +++ b/samples/agent-mcp-examples.yaml @@ -3,12 +3,7 @@ version: 1 agent: - tools: - read: true - write: true - bash: true - - mcp_servers: + mcp: # 1. Stdio MCP Server (command + args) # Runs a local process with stdin/stdout communication serena: diff --git a/samples/agent-step-level.yaml b/samples/agent-step-level.yaml index 78a5816..ea73f0c 100644 --- a/samples/agent-step-level.yaml +++ b/samples/agent-step-level.yaml @@ -1,5 +1,5 @@ # Step-level Agent Example -# Demonstrates StepAgent with tools, mcp_servers, rules, skills at step level +# Demonstrates StepAgent with mcp, rules, skills at step level # Step-level config merges with pipeline-level config version: 1 @@ -30,14 +30,7 @@ pipeline: env: ANTHROPIC_API_KEY: <+inputs.llmConnector.token> # Agent-specific fields at step level - tools: - read: true - write: false # Read-only for code review - grep: true - bash: - - "git diff" - - "git log" - mcp_servers: + mcp: github: url: https://api.github.com/mcp headers: diff --git a/schema/agent.ts b/schema/agent.ts index 7991b8a..c364603 100644 --- a/schema/agent.ts +++ b/schema/agent.ts @@ -1,37 +1,9 @@ import { Pipeline } from "./pipeline"; +import { Container } from "./container"; -// -// Built-in Tools Configuration -// - -/** - * Tools configures built-in tools available to the agent. - * @x-go-file tools.go - */ -export interface Tools { - /** - * Read enables file read capability. - */ - read?: boolean; - - /** - * Write enables file write capability. - */ - write?: boolean; - - /** - * Grep enables grep/search capability. - */ - grep?: boolean; - - /** - * Bash configures shell command execution. - * - true: enables default safe commands - * - false: disables bash - * - string[]: list of allowed commands (e.g., ["echo", "ls", "git:*"]) - */ - bash?: boolean | string[]; -} +// Built-in tools (read, write, grep, bash) are all available to the agent +// by default. Containerization provides the security boundary, so per-tool +// restrictions are not supported at this time. // // MCP Server Configuration @@ -56,10 +28,11 @@ export interface McpServer { args?: string[]; /** - * Container specifies a Docker image for container-based MCP servers. - * The container is run with stdin/stdout communication. + * Container specifies a container for running MCP servers. + * Supports string shorthand (image name) or full Container configuration + * with connector for auth, volumes, environment, etc. */ - container?: string; + container?: Container; /** * Url specifies the HTTP endpoint for remote MCP servers. @@ -96,26 +69,24 @@ export interface McpServer { // /** - * Agent extends Pipeline with AI agent-specific configuration. Agents are pipelines that can leverage AI capabilities including built-in tools, MCP servers, rules, and skills. This is a top-level alias for Pipeline with agent-specific fields. Use this when the entire pipeline is an AI agent workflow. + * Agent extends Pipeline with AI agent-specific configuration. Agents are pipelines that can leverage AI capabilities including MCP servers, rules, and skills. All built-in tools (read, write, grep, bash) are available by default. This is a top-level alias for Pipeline with agent-specific fields. Use this when the entire pipeline is an AI agent workflow. * @x-go-file agent.go */ export interface Agent extends Pipeline { /** - * Tools configures built-in tools available to all agent steps. - * Step-level tools configuration will be merged with this. - */ - tools?: Tools; - - /** - * McpServers defines Model Context Protocol servers available to all agent steps. - * Step-level mcp_servers configuration will be merged with this. + * Mcp defines Model Context Protocol servers available to all agent steps. + * Step-level mcp configuration will be merged with this. */ - mcp_servers?: Record; + mcp?: Record; /** * Rules defines behavioral constraints for the agent. - * Can be file paths (e.g., "./agents.md") or inline rule text. - * Validation engine determines if value is a path or inline content. + * Values can be: + * - File paths (e.g., "./agents.md") + * - Inline rule text (e.g., "Never modify files outside the repository root") + * - Entity references (e.g., "account.golang", "org.security", "project.*") + * which read rules stored at the account, org, or project level. + * Validation engine determines the type of each value. */ rules?: string[]; diff --git a/schema/steps.ts b/schema/steps.ts index a7c408c..8e33366 100644 --- a/schema/steps.ts +++ b/schema/steps.ts @@ -1,4 +1,4 @@ -import {Tools, McpServer} from "./agent"; +import {McpServer} from "./agent"; import {Container} from "./container"; import {CloneRef} from "./clone"; import {FailureStrategy} from "./failure"; @@ -482,7 +482,7 @@ export type Delegate = "inherit-from-infrastrcuture" | string | string[]; // /** - * StepAgent defines an AI agent step configuration. Agent-specific fields (tools, mcp_servers, rules, skills) at step level are merged with pipeline-level Agent configuration using merge strategy. + * StepAgent defines an AI agent step configuration. Agent-specific fields (mcp, rules, skills) at step level are merged with pipeline-level Agent configuration using merge strategy. * @x-go-file step_agent.go */ export interface StepAgent { @@ -502,19 +502,15 @@ export interface StepAgent { with?: Record; /** - * Tools configures built-in tools for this agent step. - * Merged with pipeline-level tools configuration. + * Mcp defines MCP servers for this agent step. + * Merged with pipeline-level mcp configuration. */ - tools?: Tools; - - /** - * McpServers defines MCP servers for this agent step. - * Merged with pipeline-level mcp_servers configuration. - */ - mcp_servers?: Record; + mcp?: Record; /** * Rules defines behavioral constraints for this agent step. + * Supports file paths, inline text, and entity references + * (e.g., "account.golang", "project.*"). * Merged with pipeline-level rules. */ rules?: string[];