Create agent
A collection of structured AI agent skills that enable Claude Code, Cursor, GitHub Copilot, and other AI coding assistants to create, operate, debug, and govern Harness CI/CD workflows through natural language.
npx -y skills add harness/harness-skills --skill create-agentAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
What its author says it does
Copied from the file, not written here
Create and update Harness AI agent instances - standalone templates for agentic workflows in pipelines. Use when asked to create agent, update agent, modify agent spec, build autonomous systems, or work with AI agents.
The file declares its own license as Apache-2.0. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
21.4 KB, as published. Nobody here has run it
Custom AI Agents
Create and update Harness AI agent instances - standalone templates used as building blocks in pipelines for automated code, agentic workflows, and infrastructure tasks.
Instructions
Follow this workflow to create or update an agent. This is INTERACTIVE — show YAML for review and wait for confirmation before creating/updating the agent.
Phase 1: Check Existing Solutions First
IMPORTANT: Before creating a new agent, check if an existing one can solve the use case.
- List existing agents — Call
harness_listwithresource_type="agent"(includeorg_idandproject_idif scoped to a project)- Check if any system or custom agents already exist that can handle this task
- Ask user if they want to use/modify an existing agent instead of creating new
- For updating existing agents — Use
harness_getwithresource_type="agent"andagent_idto retrieve the current agent configuration- Review the current
spec,name,description, and other fields - Identify what needs to be changed (spec, name, description, wiki, logo)
- Use
harness_update(notharness_create) to update the agent with only the fields that need modification
- Review the current
Phase 2: Requirements Gathering
If creating a new agent or updating an existing one, collect the following before generating YAML:
1. Agent Metadata
- Name: Display name for the agent (e.g. "Code Coverage Agent", "PR Reviewer")
- Description: Brief description of the agent's purpose (optional)
- UID/UUID: Always generate this from the name and pass it explicitly to create/update APIs. Do not rely on the create API fallback.
- Generation rule : prefix with
ca_, then lowercase the name, convert spaces and hyphens (-) to_, replace any remaining non-alphanumeric runs with_, collapse duplicate_, and trim leading/trailing_from the slug portion (e.g. "Code Coverage Agent" →ca_code_coverage_agent, "PR Reviewer" →ca_pr_reviewer) - If the generated UID conflicts with an existing agent, ask the user whether to reuse/update that agent or append a short suffix
- Generation rule : prefix with
2. Task Details - Interactive Requirements Gathering
Ask and clarify the following with the user:
- Agent's exact goal: What specific outcome should the agent achieve? Be specific — avoid vague goals.
- Inputs the agent needs: Repository info? Execution context? Configuration? Secrets?
- Outputs the agent produces: Files? External actions? Data/metrics?
- What the agent works on: Specific file paths? External services? Databases/APIs?
- Task workflow: Step-by-step workflow (do 1, then 2, then 3, etc.)
- Constraints and preferences: Limitations, rules, or coding standards (e.g., "Use idiomatic Go code", "Do not modify existing tests")
- Definition of done: How do you know the agent succeeded? Specific criteria, artifacts, or exit conditions.
3. Recommend Configuration
Based on requirements, recommend and verify with the user:
-
Task instructions (
taskfield):- Break down the goal into detailed step-by-step instructions
- Include specific commands, file paths, and expected outcomes
- Reference inputs using
${{inputs.fieldName}}syntax insidePLUGIN_TASKand other env vars - Add
## RULESsection at the end with constraints formatted as markdown bullet points
-
Runtime inputs (
inputssection in spec):- Only add if user confirms runtime parameters are needed
- Map each input to what the agent needs (repo, branch, executionId, thresholds, etc.)
- Always set a
defaultvalue for every non-required input — if${{inputs.fieldName}}is referenced inPLUGIN_TASKor any env var and no value is supplied at runtime nor a default exists, the agent will error at execution time - Always include
allowedDomainsso users understand and control non-LLM/non-MCP network access
-
Connectors:
- LLM connector for model access (required for all agents) - User must create via Harness UI or MCP
- MCP connectors for external services (GitHub, Slack, Harness platform, etc.) - only if needed
- All authentication and secrets are managed within the connectors
Present this recommended configuration to the user and iterate until confirmed.
4. Default Configuration & Inputs
Agent Structure: Agents use agent.step.group.steps format — the run step is nested inside a named step group.
Default structure:
version: 1
agent:
step:
group:
steps:
- name: Agent
if: <+Always>
id: agent
run:
container:
image: pkg.harness.io/vrvdt5ius7uwygso8s0bia/harness-agents/harness-ai-agent:latest
env:
PLUGIN_TASK: |
<step-by-step task instructions>
PLUGIN_MAX_TURNS: 150
PLUGIN_HARNESS_CONNECTOR: ${{inputs.llmConnector.id}}
PLUGIN_ALLOWED_DOMAINS: ${{inputs.allowedDomains}}
Required environment variables:
env:
PLUGIN_TASK: | # Task instructions go here as a multiline string
<step-by-step instructions>
PLUGIN_MAX_TURNS: 150 # Adjust 100-200 based on task complexity
PLUGIN_HARNESS_CONNECTOR: ${{inputs.llmConnector.id}} # References llmConnector input's id property
PLUGIN_ALLOWED_DOMAINS: ${{inputs.allowedDomains}} # Regexes for additional network access
MCP configuration (only if external services needed):
env:
PLUGIN_MCP_FORMAT: harness
PLUGIN_MCP_SERVERS: <+connectorInputs.resolveList(<+inputs.mcpConnectors>)> # References mcpConnectors input
Optional model override (only if user explicitly requests it):
env:
ANTHROPIC_MODEL: ${{inputs.modelName}} # Only add when user insists on a modelName input
Required inputs (always include):
agent:
inputs:
llmConnector:
type: connector
required: true
default: your_llm_connector_id # User must replace with actual connector ID
ui:
connectorCategories:
- AI
allowedDomains:
type: string
default: ""
Network access: Agent network access is limited to the LLM connector, configured MCP connectors, and domains matching allowedDomains. allowedDomains accepts regexes separated by |. Default to an empty string if the user does not specify domains; if they do specify domains, work with them to build the right regex.
Optional inputs (add as needed):
# MCP connectors - only if agent needs external services
mcpConnectors:
type: array
default:
- your_github_mcp_connector # User must replace
- your_slack_mcp_connector # User must replace
ui:
component: array
input:
inputType: connector
inputConfig:
connectorTypes:
- Mcp
# Model name override - ONLY add if user explicitly requests it
modelName:
type: string
default: your_model_arn_or_id # User must replace with their model ARN or ID
# Custom parameters
repo_name:
type: string
default: my-org/my-repo
layout block (always include, only list fields that are present as inputs):
The layout block controls what appears in the agent configuration UI. It contains at most four items — llmConnector, allowedDomains, modelName, and mcpConnectors — and only those that exist as first-class input fields in the inputs section. Never include any other fields (e.g. custom inputs like repo_name) in the layout block:
agent:
layout:
- title: Agent Configuration
items:
- llmConnector # always present
- allowedDomains # always present
- modelName # only if modelName input exists
- mcpConnectors # only if mcpConnectors input exists
Supported input types: string, secret, boolean, connector, array
IMPORTANT: Users must create connectors via Harness UI or harness_create with resource_type="connector" before running the agent.
Phase 3: Generate Agent Spec
Assemble the complete agent YAML specification (spec field):
- Start with
version: 1andagent:structure - Create
agent.step.group.stepsblock with a single step entry:name: Agent,if: <+Always>,id: agentrun.container.image: pkg.harness.io/vrvdt5ius7uwygso8s0bia/harness-agents/harness-ai-agent:latestrun.envsection (all task config lives here as env vars):PLUGIN_TASK:— multiline string with step-by-step instructions and## RULESsectionPLUGIN_MAX_TURNS: 150(adjust 100-200 based on complexity)PLUGIN_HARNESS_CONNECTOR: ${{inputs.llmConnector.id}}PLUGIN_ALLOWED_DOMAINS: ${{inputs.allowedDomains}}PLUGIN_MCP_FORMAT: harness(only if MCPs needed)PLUGIN_MCP_SERVERS: <+connectorInputs.resolveList(<+inputs.mcpConnectors>)>(only if MCPs needed)ANTHROPIC_MODEL: ${{inputs.modelName}}(only if user explicitly requests amodelNameinput)
- Add
agent.inputssection with:llmConnector(required) withui.connectorCategories: [AI]allowedDomains(default"") to allow additional network domains using regexesmcpConnectors(optional - only if needed) withui.component: array,ui.input.inputType: connector, andui.input.inputConfig.connectorTypes: [Mcp]modelName(optional - only if user explicitly requests it)- Custom inputs (as needed)
- Add
agent.layoutblock — only include items that are present as inputs:- Always include
llmConnector - Always include
allowedDomains - Include
modelNameonly if that input exists - Include
mcpConnectorsonly if that input exists
- Always include
Always notify users to create connectors and replace placeholder IDs before running the agent.
Phase 4: Present for Review
Present the complete agent configuration to the user:
- Agent metadata (name, description, uid)
- Full spec YAML
- Required connectors
Wait for explicit confirmation before creating/updating the agent.
Phase 5: Create or Update Agent
Only after confirmation, use harness_create to create a new agent or harness_update to update an existing one:
Creating a New Agent
Call MCP tool: harness_create
Parameters:
resource_type: "agent"
org_id: "<organization>"
project_id: "<project>"
body: {
uid: "<generated_from_agent_name>",
name: "<Agent Display Name>",
description: "<Brief description of agent purpose>",
spec: "<agent YAML spec as a string>",
wiki: "<optional: markdown documentation>"
}
Key fields for creation:
uid(required): Unique identifier. Always generate fromnameasca_<slug>and send explicitly (e.g. "Code Coverage Agent" →ca_code_coverage_agent). Do not omit it or rely on API-side auto-generation.name(required): Display name for the agentdescription(optional): Brief descriptionspec(required): The full agent YAML specification as a string (includesversion: 1,agent:,agent.step.group.steps,agent.inputs, andagent.layout)wiki(optional): Markdown documentation for the agent
Updating an Existing Agent
Call MCP tool: harness_update
Parameters:
resource_type: "agent"
resource_id: "<agent_identifier>"
org_id: "<organization>"
project_id: "<project>"
body: {
name: "<Updated Display Name>", # optional
description: "<Updated description>", # optional
spec: "<updated agent YAML spec>", # optional
wiki: "<updated markdown docs>" # optional
}
Key notes for updates:
- All fields in the body are optional — only provide fields you want to update
- Only custom agents (role='custom') can be updated; system agents cannot be modified
- The
specfield replaces the entire agent specification when provided - Use
harness_getfirst to retrieve the current agent configuration before updating
Example: Code Review Agent
version: 1
agent:
step:
group:
steps:
- name: Agent
if: <+Always>
id: agent
run:
container:
image: pkg.harness.io/vrvdt5ius7uwygso8s0bia/harness-agents/harness-ai-agent:latest
env:
PLUGIN_TASK: |
Review the pull request for repository ${{inputs.repo_name}} on branch ${{inputs.branch}}.
1. Analyze code changes for security vulnerabilities
2. Check for code quality issues
3. Verify test coverage
4. Post review comments using GitHub MCP tools
## RULES
- Focus on critical security issues first
- Be constructive in feedback
- Suggest specific code improvements
PLUGIN_MAX_TURNS: 150
PLUGIN_HARNESS_CONNECTOR: ${{inputs.llmConnector.id}}
PLUGIN_ALLOWED_DOMAINS: ${{inputs.allowedDomains}}
PLUGIN_MCP_FORMAT: harness
PLUGIN_MCP_SERVERS: <+connectorInputs.resolveList(<+inputs.mcpConnectors>)>
inputs:
llmConnector:
type: connector
required: true
default: your_llm_connector_id # User must replace with actual connector ID
ui:
connectorCategories:
- AI
allowedDomains:
type: string
default: ""
mcpConnectors:
type: array
default:
- your_github_mcp_connector # User must replace with actual connector ID
ui:
component: array
input:
inputType: connector
inputConfig:
connectorTypes:
- Mcp
repo_name:
type: string
default: my-org/my-repo
branch:
type: string
default: main
layout:
- title: Agent Configuration
items:
- llmConnector
- allowedDomains
- mcpConnectors
Using Agents in Pipelines
Once an agent is created, it is published as a template and can be used in pipelines. The agent can be referenced in both v0 and v1 pipeline YAML formats.
v1 Pipeline YAML (Template-based)
In v1 pipelines, the agent template exposes its custom inputs (excluding llmConnector and mcpConnectors, which are handled internally).
Example: Using Code Review Agent in a v1 Pipeline
Assuming you created a "Code Review Agent" with custom inputs repo_name and branch:
pipeline:
identifier: code_review_pipeline
name: Code Review Pipeline
inputs:
repo_name:
type: string
default: my-org/my-repo
branch:
type: string
default: feature/new-feature
stages:
- name: Code Review
steps:
- name: review_pr
template:
uses: [email protected]
with:
repo_name: <+inputs.repo_name>
branch: <+inputs.branch>
Key points:
- Pipeline-level
inputs:section defines runtime parameters uses: <agent_uid>@<version>references the published agent templatewith:block provides values for the agent's custom inputs using<+inputs.variableName>syntaxllmConnectorandmcpConnectorsare configured at the agent level by defaultmodelNameis optional — only present in the agent if the user explicitly requested it- Optionally, you can override
llmConnector(andmodelNameif it exists) at the pipeline level if needed - Only custom inputs (like
repo_name,branch, thresholds, etc.) are passed in the pipeline
v0 Pipeline YAML (Agent Step Type)
In v0 pipelines, agents are referenced using the Agent step type, which internally references the v1 template. The step expands the v1 template and converts it to a v0 Run Step.
Example: Using Code Review Agent in a v0 Pipeline
pipeline:
stages:
- stage:
type: Deployment
spec:
execution:
steps:
- stepGroup:
stepGroupInfra:
type: KubernetesDirect
steps:
- step:
type: Agent
name: ReviewPRAgent
identifier: ReviewPRAgent
spec:
agentName: ca_code_review_agent
agentSettings: |-
{
"repo_name": "my-org/my-repo",
"branch": "feature/new-feature",
"llmConnector": "your_llm_connector_id",
"modelName": "your_model_arn_or_id",
"mcpConnectors": ["your_github_mcp_connector", "your_slack_mcp_connector"]
}
llmConnector: your_llm_connector_id
mcpConnectors:
- your_github_mcp_connector
Key fields explained:
type: Agent- Step type for v0 pipelines that references a v1 agent templatename(required) - Display name for the step in the pipeline UIidentifier(required) - Unique identifier for the step within the pipelineagentName(required) - The agent's UID (v1 template identifier) created viaharness_createagentSettings(optional) - JSON string containing template inputs for the agent:- Custom inputs: Agent-specific fields like
repo_name,branch, thresholds, etc. - llmConnector: LLM connector ID (overrides agent default and first-class field)
- modelName: Model ARN or ID — only present if the agent was created with a
modelNameinput - mcpConnectors: Array of MCP connector IDs (overrides agent default and first-class field)
- Custom inputs: Agent-specific fields like
llmConnector(optional) - First-class field to specify LLM connector ID at pipeline levelmcpConnectors(optional) - First-class array field to specify MCP connector IDs at pipeline level
Precedence rules:
- Values in
agentSettingsJSON have highest precedence - they override both agent defaults and first-class fields - First-class fields (
llmConnector,mcpConnectors) override agent defaults - If neither are provided, the agent's default configuration from the template is used
CRITICAL GUIDELINES
These are essential rules you MUST follow when creating/updating agents:
| Guideline | Rule |
|---|---|
| Check existing first | Always call harness_list(resource_type="agent") to see if an existing agent can solve the use case before creating new |
| Updating agents | Use harness_get to retrieve current config, then harness_update (not harness_create) to modify. Only custom agents can be updated. |
| Generate UID | Always derive uid as ca_<slug> (e.g. "Code Coverage Agent" → ca_code_coverage_agent) — matches platform UI nameToUid(). Pass it explicitly; do not rely on create API fallback. |
| Agent spec format | The spec field uses agent.step.group.steps structure — the run step is nested inside a named group with name: Agent, if: <+Always>, id: agent |
| Task in env | Task instructions go in PLUGIN_TASK env var (multiline string). Max turns in PLUGIN_MAX_TURNS. There is no with: block. |
| Expression syntax | Use ${{inputs.fieldName}} inside env values. Use <+connectorInputs.resolveList(...)> for MCP server resolution. |
| modelName is optional | Do NOT add modelName input or ANTHROPIC_MODEL env var by default — only add when the user explicitly requests it |
| Allowed domains | Always include PLUGIN_ALLOWED_DOMAINS: ${{inputs.allowedDomains}}, an allowedDomains string input with default "", and allowedDomains in layout. If the user specifies domains, help build the regex. |
| Input defaults | Every non-required input that is referenced via ${{inputs.fieldName}} must have a default value — omitting it causes a runtime error if the caller does not supply the value |
| Connector placeholders | Always use placeholders like your_llm_connector_id and your_mcp_connector_id and notify users to replace both LLM and MCP connector IDs with actual values before running the agent |
| No clone/platform | Do NOT add clone, platform, os, arch, or allowed_tools sections — agents are standalone with simplified structure |
| Quality first | Agent quality is paramount — verify YAML structure, validate all references, ensure complete task instructions before creating |