Skip to main content
SkillsFlow is GitAgent’s workflow engine. It lets you define deterministic multi-step sequences that call skills in a specific order — with branching, loops, and parallel execution — without relying on the LLM to sequence every step.

When to use SkillsFlow

Use the LLM to sequence skills (default) when the agent needs to reason about which skills to call and in what order based on the user’s request. Use SkillsFlow when the sequence is known in advance: “always fetch data, then clean it, then summarize it.” SkillsFlow gives you predictability, lower token usage, and easier testing.

Defining a flow

Flows are YAML files in the flows/ directory:
# flows/research_report.yaml
name: research-report
description: "Research a topic and write a formatted report"

input:
  topic:
    type: string
    description: "The topic to research"

steps:
  - id: search
    skill: search_web
    input:
      query: "{{ input.topic }} recent developments 2024"
      num_results: 10

  - id: fetch_articles
    skill: fetch_url
    foreach: "{{ steps.search.output }}"   # loop over search results
    input:
      url: "{{ item.url }}"

  - id: summarize
    skill: summarize_text
    input:
      texts: "{{ steps.fetch_articles.output | map('content') }}"
      max_length: 500

  - id: write_report
    skill: write_document
    input:
      title: "{{ input.topic }}"
      sections: "{{ steps.summarize.output }}"

output: "{{ steps.write_report.output }}"

Running a flow

# Run a flow directly
gitagent flow run research-report --input '{"topic": "quantum computing"}'

# Run via the agent (agent decides when to use it)
gitagent run "Write a report on quantum computing"
Flows are automatically discovered by the agent and exposed as skills. The agent can choose to invoke a flow the same way it invokes a single skill.

Step types

Skill step

- id: my_step
  skill: skill_name
  input:
    arg1: "{{ expression }}"

Parallel step

Run multiple skills simultaneously:
- id: parallel_research
  parallel:
    - skill: search_web
      input:
        query: "{{ input.topic }} news"
    - skill: search_web
      input:
        query: "{{ input.topic }} papers"
    - skill: fetch_url
      input:
        url: "https://wikipedia.org/wiki/{{ input.topic }}"
  # output: list of results from all parallel branches

Conditional step

- id: check_length
  condition: "{{ steps.fetch.output.length > 1000 }}"
  then:
    skill: summarize_text
    input:
      text: "{{ steps.fetch.output }}"
  else:
    skill: passthrough
    input:
      value: "{{ steps.fetch.output }}"

Loop step

- id: process_items
  foreach: "{{ steps.list_files.output }}"
  skill: process_file
  input:
    path: "{{ item.path }}"
  # output: list of results, one per item
Limit concurrent iterations:
- id: process_items
  foreach: "{{ steps.list_files.output }}"
  concurrency: 3        # process 3 files at a time
  skill: process_file
  input:
    path: "{{ item.path }}"

Sub-flow step

- id: run_sub_workflow
  flow: another-flow    # references flows/another-flow.yaml
  input:
    param: "{{ steps.previous.output }}"

Expressions

Expressions use Jinja2 syntax inside {{ }}:
# Access flow input
"{{ input.topic }}"

# Access a previous step's output
"{{ steps.search.output }}"

# Access a field of the output
"{{ steps.search.output.results[0].url }}"

# Apply filters
"{{ steps.text.output | upper }}"
"{{ steps.items.output | length }}"
"{{ steps.items.output | map('title') | join(', ') }}"

# Conditional expression
"{{ steps.result.output if steps.result.output else 'No result' }}"

Error handling

steps:
  - id: fetch_data
    skill: fetch_url
    input:
      url: "{{ input.url }}"
    on_error:
      action: continue     # continue | stop | retry
      fallback: "Failed to fetch"

  - id: parse
    skill: parse_json
    input:
      text: "{{ steps.fetch_data.output }}"
    retry:
      max_attempts: 3
      delay_seconds: 2

Testing flows

gitagent flow test research-report \
  --input '{"topic": "AI safety"}' \
  --mock-skills              # mock skill calls, test the routing logic only
Test with real skills:
gitagent flow run research-report \
  --input '{"topic": "AI safety"}' \
  --dry-run                  # print what would be called without calling

Flow as LLM tool

The agent exposes each flow as a skill to the LLM. The flow’s name and description determine when the LLM chooses to invoke it — the same rules as individual skills apply. To prevent a flow from being exposed to the LLM (run only via gitagent flow run):
# flows/internal-batch.yaml
name: internal-batch
expose_as_skill: false