AI Teammate Configuration Guide

→ See also: Agent Best Practices for critical patterns, common helpers, and lessons learned from real-world development

CRITICAL: The “name” Field Maps to a Supported Job Identifier

READ THIS FIRST - The "name" field is NOT customizable:

{
  "name": "TestCasesGenerator"  // ← Exact Java class name (immutable)
}

This is a technical identifier for job instantiation:

  • "TestCasesGenerator"new TestCasesGenerator()
  • "Teammate"new Teammate()
  • "Expert"new Expert()

Rules:

  • Use the supported names from Jobs Reference
  • Most jobs use the exact Java class name
  • Report docs and examples use ReportGenerator / ReportVisualizer; internal aliases ReportGeneratorJob / ReportVisualizerJob are [deprecated] -> use ReportGenerator / ReportVisualizer
  • KB docs should use KBProcessing; internal alias KBProcessingJob is [deprecated] -> use KBProcessing
  • Do NOT customize: “My Generator” will fail
  • Do NOT change case: “testcasesgenerator” will fail

See JSON Configuration Rules for complete explanation.


Overview

AI Teammates are JSON-configured workflows that combine AI analysis with pre/post-processing JavaScript agents. They enable complex automation scenarios like test generation, code analysis, and documentation creation.

Common job reference

JobSummaryAccepted nameExample
TeammateOrchestrates ticket context, AI instructions, and optional CLI or JS hooks for end-to-end workflow automation.Teammatestory_development.json
JSRunnerExecutes one GraalJS script with DMtools context for isolated automation, debugging, and JS agent testing.JSRunnerrun_all.json
TestCasesGeneratorGenerates related and net-new test cases from tracker tickets, then creates or posts the configured output.TestCasesGeneratortest_cases_generator.json
InstructionsGeneratorBuilds reusable implementation instructions from tracker tickets and writes them to Confluence or a local file.InstructionsGeneratorinstructions-generator-job.json
DevProductivityReportProduces developer productivity metrics from tracker, source control, and optional spreadsheet inputs.DevProductivityReportdev-productivity-report.json
BAProductivityReportCalculates BA delivery metrics such as created work, field updates, and workflow movement over time.BAProductivityReportba-productivity-report.json
QAProductivityReportCalculates QA metrics such as bugs, tests, comments, and key status transitions across releases.QAProductivityReportqa-productivity-report.json
ReportGeneratorGenerates configurable analytics reports as JSON and HTML from tracker, SCM, CSV, or Figma data.ReportGenerator; ReportGeneratorJob [deprecated] -> ReportGeneratorreport-generator-job.json
ReportVisualizerRenders a saved JSON report as an interactive HTML dashboard without regenerating report data.ReportVisualizer; ReportVisualizerJob [deprecated] -> ReportVisualizerreport-visualizer-job.json
KBProcessingRuns the knowledge-base pipeline that processes source content and aggregates searchable KB output.KBProcessing; KBProcessingJob [deprecated] -> KBProcessingkb-processing-job.json

Configuration Structure

Complete Configuration Schema

{
  "name": "TestCasesGenerator",
  "params": {
    // Input Configuration
    "inputJql": "project = PROJ AND type = Story",
    "inputTicketId": "PROJ-123",
    "inputFile": "/path/to/input.json",

    // AI Configuration
    "aiProvider": "gemini",
    "aiModel": "gemini-2.0-flash-exp",
    "aiRole": "You are an expert QA engineer specializing in test case design",
    "instructions": "Generate comprehensive test cases with positive, negative, and edge cases",
    "formattingRules": "Return results as JSON array with specific structure",
    "fewShots": [
      {
        "input": "Login feature",
        "output": "Test cases for login including valid/invalid credentials"
      }
    ],

    // JavaScript Agents
    "preprocessJSAction": "agents/js/validateInput.js",
    "postprocessJSAction": "agents/js/createTickets.js",
    "skipJSAction": "agents/js/checkWipLabel.js",

    // Output Configuration
    "outputType": "field",
    "outputFieldName": "Test Cases",
    "outputFile": "/path/to/output.json",
    "outputJiraProject": "PROJ",
    "outputJiraIssueType": "Test",

    // Processing Options
    "batchSize": 10,
    "maxConcurrent": 5,
    "retryAttempts": 3,
    "skipExisting": true,
    "dryRun": false,

    // Custom Parameters
    "customField1": "value1",
    "customField2": "value2"
  }
}

Parameter Reference

Input Parameters

ParameterTypeDescriptionExample
inputJqlStringJQL query to fetch tickets"sprint in openSprints()"
inputTicketIdStringSingle ticket ID"PROJ-123"
inputFileStringPath to input file"/data/stories.json"
inputTicketsArrayDirect ticket list["PROJ-1", "PROJ-2"]

AI Configuration

ParameterTypeDescriptionExample
aiProviderStringAI provider to use"gemini", "openai", "bedrock"
aiModelStringSpecific model"gemini-2.0-flash-exp", "gpt-4o"
aiRoleStringSystem prompt/role — also supports local file paths and GitHub/Confluence URLs (same as instructions)"You are a senior developer", "./agents/roles/dev.md"
instructionsString/ArrayTask instructions — supports plain text, local file paths (./, ../, /), Confluence URLs (https://...atlassian.net/...), and GitHub URLs (https://github.com/...)"./agents/prompts/dev.md", "https://github.com/org/repo/blob/main/PROMPT.md"
formattingRulesStringOutput format rules — same source types as instructions"Return as JSON with keys: title, description", "./prompts/format.md"
fewShotsString/ArrayExample input/outputs — same source types as instructions"./prompts/few_shots.md"
temperatureFloatCreativity (0-1)0.7
maxTokensIntegerMax response tokens2000

JavaScript Actions

ParameterTypeDescriptionWhen Executed
preprocessJSActionStringJS file pathBefore AI processing
postprocessJSActionStringJS file pathAfter AI processing
skipJSActionStringJS file pathTo determine skip logic
validateJSActionStringJS file pathTo validate AI output

Custom Parameters (customParams)

customParams is a free-form key-value map that lets you pass arbitrary configuration from the JSON config into JavaScript agents. Any data type is supported: strings, numbers, booleans, nested objects, arrays.

{
  "name": "Teammate",
  "params": {
    "inputJql": "key = PROJ-123",
    "preJSAction": "agents/js/myAgent.js",
    "customParams": {
      "workflowId": "rework.yml",
      "targetBranch": "main",
      "maxRetries": 3,
      "flags": {
        "dryRun": false,
        "verbose": true
      }
    }
  }
}

Accessing customParams in a JS agent:

function action(params) {
    const custom = params.jobParams.customParams;

    const workflowId  = custom.workflowId;          // "rework.yml"
    const targetBranch = custom.targetBranch;       // "main"
    const maxRetries  = custom.maxRetries;          // 3
    const dryRun      = custom.flags.dryRun;        // false

    if (!dryRun) {
        github_trigger_workflow(
            "my-org",
            "my-repo",
            workflowId,
            JSON.stringify({ user_request: params.ticket.key }),
            targetBranch
        );
    }
}

Available params fields in JS agents:

FieldTypeDescription
params.ticketObjectCurrent Jira/ADO ticket (key, fields, status, …)
params.jobParamsObjectFull serialized job config — includes ALL params fields incl. customParams
params.jobParams.customParamsObjectYour custom key-value map
params.responseStringAI response (null in preJSAction, filled in postJSAction)
params.initiatorStringUser who triggered the job
params.inputFolderPathStringAbsolute path to input folder (preCliJSAction only)

Instruction Sources

The following fields all go through InstructionProcessor, which resolves content from four source types: instructions, additionalInstructions, formattingRules, fewShots, cliPrompt, aiRole, questions, tasks

SourceDetectionHow content is fetched
Plain textAnything elseUsed as-is
Local fileStarts with ./, ../, or /Read from disk relative to working directory
Confluence URLhttps://...atlassian.net/...Fetched via Confluence API (requires CONFLUENCE_* env vars)
GitHub URLhttps://github.com/... or https://raw.githubusercontent.com/...Fetched via GitHub API (SOURCE_GITHUB_TOKEN is optional for public repos, required for private)

If fetching fails for any reason, the original string is used as fallback — no error is thrown.

Examples:

{
  "name": "Teammate",
  "params": {
    "agentParams": {
      "instructions": [
        "https://github.com/your-org/playbook/blob/main/instructions/enhance-sd-api.md",
        "./instructions/common/jira_context.md",
        "https://company.atlassian.net/wiki/spaces/DEV/pages/123/Template",
        "**IMPORTANT** Return JSON format: {\"description\": \"...\"}"
      ],
      "formattingRules": "https://github.com/your-org/playbook/blob/main/formatting/api-ticket.md",
      "fewShots": "./agents/prompts/few_shots.md"
    }
  }
}

Private GitHub repos require SOURCE_GITHUB_TOKEN environment variable:

SOURCE_GITHUB_TOKEN=ghp_your_token_here

additionalInstructions — Append Without Replacing

additionalInstructions is a top-level params field (on TeammateParams, not inside agentParams) that lets projects add their own instructions on top of whatever instructions are defined in agentParams.

This solves the ConfigurationMerger limitation: when you override a config with a different instructions array via encoded JSON, the whole array is replaced. With additionalInstructions, your project-specific rules live in a separate field and are always appended — never replaced — regardless of how agentParams.instructions is set.

{
  "name": "Teammate",
  "params": {
    "agentParams": {
      "instructions": [
        "https://github.com/your-org/shared-playbook/blob/main/instructions/default.md"
      ]
    },
    "additionalInstructions": [
      "https://yourcompany.atlassian.net/wiki/spaces/PROJ/pages/123",
      "./instructions/project-specific-rules.md",
      "Always use our internal API naming convention."
    ]
  }
}

How it works:

  1. agentParams.instructions is resolved via InstructionProcessor (URLs/files → content)
  2. additionalInstructions is resolved the same way (same source types: plain text, file, Confluence, GitHub)
  3. The resolved additional instructions are appended to the resolved base instructions
  4. The AI receives one combined array: [...instructions, ...additionalInstructions]

When to use it:

  • You have a shared base config (e.g. from GitHub) that you don’t want to copy
  • Your project has Confluence pages or local files with project-specific rules
  • You want CI/CD to inject extra context without touching agentParams
FieldLocationBehavior on override
agentParams.instructionsInside agentParamsReplaced entirely by ConfigurationMerger
additionalInstructionsTop-level paramsAlways appended — independent field

CLI Integration (NEW in v1.7.130+)

ParameterTypeDefaultDescriptionExample
cliPromptString-Single prompt for CLI agent (supports plain text, local file paths, Confluence URLs, GitHub URLs)"Implement from input/", "./prompts/dev.md", "https://github.com/org/repo/blob/main/PROMPT.md"
cliPromptsArray-Array of prompts — each entry is extracted via InstructionProcessor and all parts are joined with \n\n into one combined prompt. Combined with cliPrompt if both are set (cliPrompt comes first). Supports the same sources as cliPrompt.["./base.md", "https://confluence.co/...", "Also apply coding standards"]
cliCommandsArray-CLI commands to execute["./cicd/scripts/run-cursor-agent.sh"]
preCliJSActionString-JS script path executed after input folder is created but before CLI commands run. Receives params.inputFolderPath (absolute path). Use to write extra files into the input folder. Errors in this script are logged but do NOT stop CLI execution."agents/js/extendInputFolder.js"
timerJSActionString-JS script path executed periodically in a background thread while CLI commands are running. Receives the same params as postJSAction + params.currentCliOutput (accumulated stdout so far), plus params.currentCliHasFatalError (boolean) and params.currentCliErrorMessage (string, may be null) — set as soon as a CLI command fails with a non-zero exit code, so retry logic can distinguish a real, non-retryable failure from a transient interruption. Use for side-effects like auto-committing, posting progress, or sending notifications. Errors are logged and never abort CLI execution."agents/js/autoCommit.js"
timerIntervalSecondsInteger60Interval in seconds between timerJSAction executions. Timer starts after the first interval elapses. Has no effect when timerJSAction is not set or when value is ≤ 0.300
skipAIProcessingBooleanfalseSkip AI processing when using CLI agentstrue
requireCliOutputFileBooleantrueNEW v1.7.133: Require output/response.md before updating fields (strict mode prevents data loss)true (recommended)
cleanupInputFolderBooleantrueNEW v1.7.133: Cleanup input/[TICKET-KEY]/ folder after executionfalse (for debugging)
writeAgentParamsToFilesBooleanfalseWrite agent params (instructions, aiRole, knownInfo, formattingRules, fewShots) as separate files in the input folder. Keeps request.md minimal (ticket info only). See below.true

Example with cliPrompt field:

{
  "name": "Teammate",
  "params": {
    "cliPrompt": "Implement the ticket from input/ folder. Write results to output/.",
    "cliCommands": ["./cicd/scripts/run-cursor-agent.sh"],
    "skipAIProcessing": true,
    "postJSAction": "agents/js/developTicketAndCreatePR.js"
  }
}

Example with cliPrompts array (multiple sources combined into one prompt):

{
  "name": "Teammate",
  "params": {
    "cliPrompts": [
      "https://confluence.company.com/wiki/pages/base-instructions",
      "./agents/prompts/coding-standards.md",
      "Write results to outputs/response.md"
    ],
    "cliCommands": ["./cicd/scripts/run-cursor-agent.sh"]
  }
}

Example — cliPrompt + cliPrompts combined (cliPrompt content comes first):

{
  "name": "Teammate",
  "params": {
    "cliPrompt": "## Base Instructions\nAlways follow the project coding standards.",
    "cliPrompts": [
      "https://confluence.company.com/wiki/pages/extra-context",
      "./agents/prompts/output-format.md"
    ],
    "cliCommands": ["./cicd/scripts/run-cursor-agent.sh"]
  }
}

Or use file-based prompt for reusability:

{
  "cliPrompt": "./agents/prompts/implementation_prompt.md",
  "cliCommands": ["./cicd/scripts/run-cursor-agent.sh"]
}

Or Confluence URL for centralized management:

{
  "cliPrompt": "https://company.atlassian.net/wiki/spaces/DEV/pages/123/Prompt",
  "cliCommands": ["./cicd/scripts/run-cursor-agent.sh"]
}

Or GitHub URL (public or private with SOURCE_GITHUB_TOKEN):

{
  "cliPrompt": "https://github.com/your-org/your-repo/blob/main/agents/prompts/implement.md",
  "cliCommands": ["./cicd/scripts/run-cursor-agent.sh"]
}

How it works:

  1. Teammate calls InstructionProcessor.buildCombinedPrompt(cliPrompt, cliPrompts) which fetches URLs/files and joins all parts with \n\n
  2. Combined prompt is written to a temp file
  3. Temp file path is appended as a quoted parameter to each CLI command
  4. Example: ./script.sh becomes ./script.sh "/tmp/dmtools_cli_prompt_xxx.txt"

See CLI Integration Guide for complete documentation.

Structured cliPrompts with named sections (NEW)

cliPrompts can also be a mixed array of plain strings and named section objects. Named sections let you group related prompts and override only specific parts when inheriting configs.

Format:

{
  "cliPrompts": [
    "./agents/prompts/base.md",
    { "id": "input",    "prompts": ["./agents/prompts/input.md"] },
    { "id": "output",   "prompts": ["./agents/prompts/output.md"], "mergeStrategy": "append" },
    { "id": "template", "prompts": ["./agents/prompts/template.md"] }
  ]
}

Merge rules when a child config inherits from a parent:

  • Unnamed strings keep their original position in the array.
  • Sections with the same id are merged according to mergeStrategy:
    • append (default) — child prompts are appended to parent prompts
    • prepend — child prompts are inserted before parent prompts
    • replace — child prompts completely replace parent prompts
  • Sections with new ids and unnamed strings from the child config are appended to the end.

Example — base agent config:

{
  "name": "base_agent",
  "params": {
    "cliPrompts": [
      "./prompts/common/role.md",
      { "id": "input",  "prompts": ["./prompts/common/input.md"] },
      { "id": "output", "prompts": ["./prompts/common/output.md"] }
    ]
  }
}

Example — child config overriding only output:

{
  "extends": "base_agent",
  "params": {
    "cliPrompts": [
      { "id": "output", "prompts": ["./prompts/specialized/output.md"], "mergeStrategy": "replace" }
    ]
  }
}

The resulting merged cliPrompts would be equivalent to:

[
  "./prompts/common/role.md",
  { "id": "input",  "prompts": ["./prompts/common/input.md"] },
  { "id": "output", "prompts": ["./prompts/specialized/output.md"] }
]

Plain string arrays are still fully supported and are treated as unnamed prompts.

writeAgentParamsToFiles

When true, instead of embedding all agent params inside request.md, each configuration item is extracted and written as a separate file in the input/[TICKET]/ folder. This keeps request.md small (ticket info only) and lets CLI agents read large context files directly.

File layout:

input/TICKET-123/
  request.md              ← minimal: ticket info only
  comments.md             ← ticket comments
  instructions/
    instruction_001.md    ← each URL or file-path instruction
    instruction_002.md
    instructions_text.md  ← all plain-text instructions combined
  ai_role.md              ← if aiRole was a URL/path
  known_info.md           ← if knownInfo was a URL/path
  formatting_rules.md     ← if formattingRules was a URL/path
  few_shots.md            ← if fewShots was a URL/path

Writing rules:

Value typeAction
URL (https://, GitHub)Fetched via InstructionProcessor → written as file
File path (/, ./, ../)Content copied to file
Plain textArrays: combined into instructions_text.md; single fields: left as-is

Example:

{
  "name": "Teammate",
  "params": {
    "cliCommands": ["./cicd/run-agent.sh"],
    "writeAgentParamsToFiles": true,
    "agentParams": {
      "aiRole":          "https://confluence.company.com/wiki/...ROLE",
      "knownInfo":       "https://confluence.company.com/wiki/...KNOWN",
      "formattingRules": "https://confluence.company.com/wiki/...FORMAT",
      "fewShots":        "https://confluence.company.com/wiki/...SHOTS",
      "instructions": [
        "https://confluence.company.com/wiki/...INSTR_1",
        "https://confluence.company.com/wiki/...INSTR_2",
        "You must write response to outputs/response.md",
        "./agents/instructions/common/bash_tools.md"
      ]
    }
  }
}

CLI Output Safety (v1.7.133+)

Problem: When CLI commands fail or don’t create output/response.md, the system could overwrite critical fields with error messages.

Solution: Two new safety parameters control CLI output handling:

requireCliOutputFile (default: true)

Strict Mode (recommended for production):

{
  "requireCliOutputFile": true,  // Default - safe mode
  "outputType": "field",
  "fieldName": "Description"
}

Behavior:

  • If output/response.md exists → Process normally (update field/post comment/create ticket)
  • If output/response.md missing → Skip field update, post error comment instead
  • Protects against data loss - won’t overwrite fields with error messages

Permissive Mode (use with caution):

{
  "requireCliOutputFile": false,  // Permissive mode
  "outputType": "field",
  "fieldName": "Notes"
}

Behavior:

  • Uses command stdout/stderr as fallback if response.md missing
  • Less safe - may update fields with error messages
  • Backwards compatible with old behavior
cleanupInputFolder (default: true)

Cleanup Enabled (recommended for production):

{
  "cleanupInputFolder": true  // Default - saves disk space
}

Behavior:

  • Automatically deletes input/[TICKET-KEY]/ folder after processing
  • Removes temporary request.md and downloaded attachments

Cleanup Disabled (for debugging):

{
  "cleanupInputFolder": false  // Keep input for inspection
}

Behavior:

  • Keeps input/[TICKET-KEY]/ folder for manual inspection
  • Allows debugging CLI issues by checking request.md and attachments
  • Requires manual cleanup: rm -rf input/[TICKET-KEY]
preCliJSAction

Runs after the input folder is created (containing request.md and ticket attachments) but before CLI commands execute. The script receives params.inputFolderPath — the absolute path to the folder.

Typical use cases: inject extra reference files (architecture docs, style guides, API specs) that the CLI agent should read as context.

// agents/js/extendInputFolder.js
function action(params) {
    const folder = params.inputFolderPath;

    // Fetch architecture guide from Confluence and add to input folder
    const architectureGuide = confluence_content_by_title("Architecture Guide");
    file_write(folder + "/architecture.md", architectureGuide);

    // Add a coding standards file
    const codingStandards = file_read("./docs/coding-standards.md");
    file_write(folder + "/coding-standards.md", codingStandards);
}
{
  "name": "Teammate",
  "params": {
    "cliCommands": ["./cicd/scripts/run-cursor-agent.sh"],
    "preCliJSAction": "agents/js/extendInputFolder.js",
    "skipAIProcessing": true
  }
}

Error handling: if preCliJSAction throws an exception, it is logged as a warning and CLI execution continues normally — the script failure never blocks the main workflow.


timerJSAction + timerIntervalSeconds

A JS script executed periodically in a background thread while the CLI commands are running. This enables side-effects like auto-committing to a branch, posting progress comments, or sending notifications — without blocking the main agent workflow.

JS context — identical to postJSAction:

  • All MCP clients (tracker, AI, Confluence) are available via executeToolViaJava
  • params contains the full Teammate config (agentParams, customParams, etc.)
  • ticket is the current Jira/ADO ticket being processed
  • Extra: params.currentCliOutput — a string snapshot of the accumulated CLI stdout up to the moment the timer fires
  • Extra: params.currentCliHasFatalErrortrue as soon as a CLI command has failed with a non-zero exit code (e.g. an invalid model ID rejected by the AI provider); false otherwise. Use this instead of string-scanning currentCliOutput to distinguish a real, non-retryable failure from a transient interruption (no output yet, still running).
  • Extra: params.currentCliErrorMessage — a concise message describing the last fatal CLI failure, or null/empty if none occurred yet.

Threading model:

  • Single daemon thread (ScheduledExecutorService)
  • scheduleAtFixedRate — fires at timerIntervalSeconds, 2×timerIntervalSeconds, …
  • First firing happens after the first full interval (not immediately)
  • Timer stops when all CLI commands finish (with a 5-second graceful shutdown)
  • Exceptions inside the timer are caught, logged, and do not abort CLI execution
{
  "name": "Teammate",
  "params": {
    "cliCommands": ["./cicd/scripts/run-cursor-agent.sh"],
    "timerJSAction": "agents/js/autoCommit.js",
    "timerIntervalSeconds": 300,
    "skipAIProcessing": true
  }
}

Example agents/js/autoCommit.js — auto-commit every 5 minutes while agent works:

const output = params.currentCliOutput || '';
const lines = output.split('\n').filter(l => l.trim());
const lastLine = lines.length > 0 ? lines[lines.length - 1].substring(0, 80) : 'wip';

// Use CLI tools available in your environment:
// executeToolViaJava('cli_run_command', { command: 'git add -A' });
// executeToolViaJava('cli_run_command', { command: 'git commit -m "wip: ' + lastLine + '"' });
print('timerJSAction fired, currentCliOutput lines: ' + lines.length);

Example: Production-safe CLI configuration:

{
  "name": "Teammate",
  "params": {
    "cliPrompt": "Generate comprehensive story description",
    "cliCommands": ["./cicd/scripts/run-cursor-agent.sh"],
    "skipAIProcessing": true,
    "requireCliOutputFile": true,   // Strict mode (default)
    "cleanupInputFolder": true,     // Cleanup (default)
    "outputType": "field",
    "fieldName": "Description",
    "operationType": "Replace",
    "initiator": "automation"
  }
}

Example: Debug mode (CLI not working):

{
  "name": "Teammate",
  "params": {
    "cliCommands": ["./cicd/scripts/run-cursor-agent.sh"],
    "skipAIProcessing": true,
    "cleanupInputFolder": false,    // Keep for debugging
    "outputType": "comment"
  }
}

After debugging: cat input/PROJ-123/request.md and ls -la input/PROJ-123/

Output Configuration

ParameterTypeDescriptionOptions
outputTypeStringOutput destination"field", "creation", "file", "none"
outputFieldNameStringJira field to update"Test Cases", "customfield_10001"
outputFileStringOutput file path"/results/tests.json"
outputJiraProjectStringProject for new tickets"PROJ"
outputJiraIssueTypeStringType for new tickets"Test", "Task", "Bug"

Real-World Examples

Example 1: Xray Test Case Generator

From agents/xray_test_cases_generator.json:

{
  "name": "TestCasesGenerator",
  "params": {
    "inputJql": "project = TP AND type = Story AND sprint in openSprints()",
    "aiProvider": "gemini",
    "aiModel": "gemini-2.0-flash-exp",
    "aiRole": "You are a highly skilled QA engineer specializing in test case design",
    "instructions": "Generate comprehensive manual test cases for the given user story. Include positive, negative, and edge cases.",
    "formattingRules": "Return as JSON array. Each test case must have: priority (Critical/High/Medium/Low), summary (brief title), description (detailed steps), testType (Manual)",
    "outputType": "creation",
    "outputJiraProject": "TP",
    "outputJiraIssueType": "Test",
    "preprocessJSAction": "agents/js/checkWipLabel.js",
    "postprocessJSAction": "agents/js/preprocessXrayTestCases.js",
    "customFields": {
      "testType": "Manual",
      "labels": ["auto-generated", "xray"]
    }
  }
}

Example 2: Cucumber Test Generator

From agents/cucumber_tests_generator.json:

{
  "name": "CucumberTestsGenerator",
  "params": {
    "inputJql": "project = PROJ AND type = Story AND 'Cucumber Tests' is EMPTY",
    "aiProvider": "openai",
    "aiModel": "gpt-4o",
    "aiRole": "You are a BDD expert who writes Cucumber scenarios",
    "instructions": "Create Cucumber scenarios using Gherkin syntax. Focus on business behavior, not implementation.",
    "formattingRules": "Use Scenario Outline for data-driven tests. Include Background when there are common preconditions.",
    "fewShots": [
      {
        "input": "User login feature",
        "output": "Feature: User Login\n  Scenario: Successful login\n    Given user is on login page\n    When user enters valid credentials\n    Then user is redirected to dashboard"
      }
    ],
    "outputType": "field",
    "outputFieldName": "Cucumber Tests",
    "validateJSAction": "agents/js/validateGherkin.js"
  }
}

Example 3: Code Review Assistant

{
  "name": "CodeReviewAssistant",
  "params": {
    "inputFile": "/src/main/java/",
    "aiProvider": "gemini",
    "aiModel": "gemini-1.5-pro-002",
    "aiRole": "You are a senior software engineer conducting code reviews",
    "instructions": "Review the code for: security issues, performance problems, code smells, SOLID violations, and suggest improvements",
    "formattingRules": "Structure feedback as: Issues (critical/major/minor), Suggestions, Good Practices observed",
    "outputType": "file",
    "outputFile": "/reports/code-review.md",
    "temperature": 0.3,
    "customRules": {
      "checkSecurity": true,
      "checkPerformance": true,
      "checkStyle": false
    }
  }
}

Example 4: Story Decomposition

From agents/story_decomposition.json:

{
  "name": "StoryDecomposer",
  "params": {
    "inputJql": "type = Epic AND status = 'To Do'",
    "aiProvider": "openai",
    "aiModel": "gpt-4o",
    "aiRole": "You are a product owner breaking down epics into user stories",
    "instructions": "Decompose the epic into 3-7 user stories. Each story should be independently deliverable and follow INVEST principles",
    "formattingRules": "Each story needs: title, description (As a... I want... So that...), acceptance criteria, story points (1,2,3,5,8)",
    "outputType": "creation",
    "outputJiraProject": "PROJ",
    "outputJiraIssueType": "Story",
    "postprocessJSAction": "agents/js/linkToEpic.js"
  }
}

Example 5: Documentation Generator

{
  "name": "DocumentationGenerator",
  "params": {
    "inputJql": "type = Story AND fixVersion = '2.0' AND 'Documentation' is EMPTY",
    "aiProvider": "gemini",
    "aiModel": "gemini-2.0-flash-exp",
    "aiRole": "You are a technical writer creating user documentation",
    "instructions": "Create user-facing documentation for the implemented feature",
    "formattingRules": "Include: Overview, Prerequisites, Step-by-step Usage, Examples, Troubleshooting, FAQ",
    "outputType": "confluence",
    "confluenceSpace": "DOCS",
    "confluenceParentPage": "User Guide",
    "postprocessJSAction": "agents/js/addScreenshots.js"
  }
}

Output Types Explained

1. Field Output ("outputType": "field")

Updates a field in the source ticket:

{
  "outputType": "field",
  "outputFieldName": "Test Cases",
  "appendToField": true  // Optional: append instead of replace
}

2. Creation Output ("outputType": "creation")

Creates new tickets:

{
  "outputType": "creation",
  "outputJiraProject": "PROJ",
  "outputJiraIssueType": "Test",
  "linkToSource": true,  // Link new tickets to source
  "linkType": "Tests"    // Relationship type
}

3. File Output ("outputType": "file")

Saves to file:

{
  "outputType": "file",
  "outputFile": "/results/output.json",
  "outputFormat": "json"  // json, csv, markdown
}

4. No Output ("outputType": "none")

For processing without output:

{
  "outputType": "none"  // Just process, don't save
}

Few-Shot Learning

Provide examples to improve AI accuracy:

{
  "fewShots": [
    {
      "input": "Login with email and password",
      "output": {
        "title": "Valid login test",
        "steps": [
          "Navigate to login page",
          "Enter valid email",
          "Enter valid password",
          "Click login button"
        ],
        "expected": "User successfully logged in and redirected to dashboard"
      }
    },
    {
      "input": "Password reset functionality",
      "output": {
        "title": "Password reset via email",
        "steps": [
          "Click 'Forgot Password'",
          "Enter registered email",
          "Check email for reset link",
          "Click reset link",
          "Enter new password",
          "Confirm password change"
        ],
        "expected": "Password successfully changed, user can login with new password"
      }
    }
  ]
}

Processing Options

Batch Processing

{
  "batchSize": 10,        // Process 10 tickets at a time
  "maxConcurrent": 5,     // Max 5 parallel AI calls
  "delayBetweenBatches": 2000  // 2 second delay
}

Error Handling

{
  "retryAttempts": 3,     // Retry failed tickets 3 times
  "continueOnError": true,  // Don't stop on single failure
  "errorFile": "/logs/errors.json"  // Log errors
}

Skip Logic

{
  "skipExisting": true,   // Skip if output already exists
  "skipJSAction": "agents/js/shouldSkip.js",  // Custom skip logic
  "skipLabels": ["skip", "manual"]  // Skip tickets with these labels
}

Running Configurations

Execute Configuration

# Run configuration file
dmtools run agents/xray_test_cases_generator.json

# With override parameters
dmtools run agents/config.json --param inputJql="project = PROJ"

# Dry run (preview without execution)
dmtools run agents/config.json --dry-run

# With debug output
dmtools run agents/config.json --debug

Test Configuration

# Validate configuration
dmtools validate agents/config.json

# Test with single ticket
dmtools run agents/config.json --param inputTicketId="PROJ-123"

# Test with limited batch
dmtools run agents/config.json --param batchSize=1

Advanced Configurations

Multi-Provider Fallback

{
  "aiProviders": [
    {
      "provider": "gemini",
      "model": "gemini-2.0-flash-exp",
      "maxRetries": 2
    },
    {
      "provider": "openai",
      "model": "gpt-4o",
      "fallback": true
    }
  ]
}

Dynamic Parameters

{
  "params": {
    "inputJql": "${env.SPRINT_JQL}",  // From environment
    "aiModel": "${config.ai.model}",  // From config file
    "outputFile": "/results/${date:yyyy-MM-dd}/tests.json"  // Date template
  }
}

Conditional Processing

{
  "conditions": {
    "processIf": {
      "field": "priority",
      "operator": "in",
      "value": ["High", "Critical"]
    },
    "skipIf": {
      "field": "labels",
      "operator": "contains",
      "value": "no-automation"
    }
  }
}

Monitoring & Logging

Progress Tracking

{
  "monitoring": {
    "showProgress": true,
    "progressInterval": 10,  // Log every 10 items
    "summaryReport": true,
    "reportFile": "/reports/execution-summary.json"
  }
}

Detailed Logging

{
  "logging": {
    "level": "DEBUG",  // ERROR, WARN, INFO, DEBUG
    "logFile": "/logs/teammate.log",
    "logAIPrompts": true,
    "logAIResponses": true,
    "logAPIcalls": false
  }
}

Common Issues

Issue: “AI provider not configured”

// Ensure AI provider credentials are set
{
  "aiProvider": "gemini",  // Requires GEMINI_API_KEY env var
  "aiProviderKey": "${env.GEMINI_API_KEY}"  // Or explicit
}

Issue: “Custom field not found”

// Map custom fields correctly
{
  "fieldMapping": {
    "customfield_10001": "StoryPoints",
    "customfield_10002": "TestCases"
  }
}

Issue: “Rate limit exceeded”

// Add rate limiting
{
  "rateLimiting": {
    "maxRequestsPerMinute": 10,
    "delayBetweenRequests": 6000  // 6 seconds
  }
}

Best Practices

1. Start Simple

Begin with minimal configuration and add complexity:

{
  "name": "SimpleTestGenerator",
  "params": {
    "inputTicketId": "PROJ-123",
    "aiProvider": "gemini",
    "instructions": "Generate 3 test cases",
    "outputType": "none"  // Just test AI response
  }
}

2. Use Preprocessing

Validate and enrich data before AI:

{
  "preprocessJSAction": "agents/js/enrichTicketData.js"
}

3. Validate Output

Always validate AI responses:

{
  "validateJSAction": "agents/js/validateOutput.js",
  "validationRules": {
    "required": ["title", "description"],
    "maxLength": { "title": 100 }
  }
}

4. Handle Errors Gracefully

{
  "errorHandling": {
    "continueOnError": true,
    "logErrors": true,
    "fallbackValue": { "status": "manual-review-needed" }
  }
}

Next: JavaScript Agent Examples | MCP Tools Usage

Edit this page on GitHub →

Rendered from dmtools-ai-docs/references/agents/teammate-configs.md, the same Markdown the DMTools agent skill reads. Last updated .