AI Inference in GitHub Actions

repository·main·Indexed 19 days ago

https://github.com/actions/ai-inference

A GitHub Action that enables AI model inferences within workflows by leveraging the GitHub Copilot CLI. It supports inline prompts, plain text files, and structured .prompt.yml files with variable injection. The action provides model responses via a raw text output or a temporary response file and supports configuration of model parameters such as temperature and maxCompletionTokens.

Tokens
4.8K
Snippets
14
Records
19
Agent score
62%

What's inside actions/ai-inference

  1. Setup and run AI inference via Copilot CLI

    main

    The actions/ai-inference action allows you to run AI inference in GitHub workflows using the GitHub Copilot CLI.

    Important Requirements:

    • The action is Copilot-only. The provider input defaults to copilot, and it is currently the only supported value.
    • The Copilot CLI is not pre-installed on GitHub-hosted runners. You must install and authenticate it before using the action.
    • Authentication is typically handled by providing a COPILOT_GITHUB_TOKEN environment variable (e.g., using a Personal Access Token stored in GitHub Secrets).

    To use the action, install the CLI globally via npm and then invoke the action in your workflow steps.

    name: AI inference
    on: workflow_dispatch
    
    jobs:
      inference:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v6
    
          - uses: actions/setup-node@v6
    
          - name: Install Copilot CLI
            run: npm install -g @github/copilot
    
          - name: Run AI Inference via Copilot
            id: inference
            uses: actions/ai-inference@v1
            with:
              prompt: Summarize the latest changes in this repository.
              model: gpt-4.1
            env:
              COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_PAT }}
    
          - name: Print output
            run: echo "${{ steps.inference.outputs.response }}"
  2. Use a system prompt file

    main

    You can separate your instructions from your user prompt by using a system-prompt-file. This file contains the system instructions that guide the model's behavior. If both system-prompt (inline) and system-prompt-file are provided, the file takes precedence.

    steps:
      - name: Run AI Inference with System Prompt File
        id: inference
        uses: actions/ai-inference@v1
        with:
          prompt: Hello
          system-prompt-file: ./.github/prompts/system.txt
  3. Provide prompts using files

    main

    You can provide prompt content either inline or by referencing external files. Using a file takes precedence over an inline prompt if both are provided.

    Text prompt files

    Use prompt-file to point to a plain .txt file containing your prompt.

    Structured .prompt.yml files

    For complex prompts, use a .prompt.yml file. This allows you to define a system message, a user message, and a model. You can inject dynamic data into the template using input (for YAML variables) and file_input (for file contents).

    Example .prompt.yml structure:

    messages:
      - role: system
        content: Be concise and concrete.
      - role: user
        content: Summarize changes for {{repo}} using this diff:\n{{diff}}
    model: gpt-4.1
    # Using a text file
    steps:
      - name: Run AI Inference with Text File
        id: inference
        uses: actions/ai-inference@v1
        with:
          prompt-file: ./.github/prompts/prompt.txt
    
    # Using a structured YAML file with variable injection
    steps:
      - name: Run AI Inference with Prompt YAML
        id: inference
        uses: actions/ai-inference@v1
        with:
          prompt-file: ./.github/prompts/sample.prompt.yml
          input: |
            repo: actions/ai-inference
          file_input: |
            diff: ./artifacts/diff.txt
  4. Configure actions/ai-inference inputs

    main

    The following inputs are available for the actions/ai-inference@v1 action:

    NameDescriptionDefault
    promptInline user prompt.""
    prompt-filePath to prompt file (.txt or .prompt.yml). Takes precedence over prompt.""
    inputYAML template variables for .prompt.yml files.""
    file_inputYAML map of template variable names to file paths; file contents are injected into templates.""
    modelModel to pass to Copilot CLI (e.g., gpt-4.1, claude-sonnet-4.5). Empty to use CLI default.gpt-4.1
    system-promptInline system prompt.You are a helpful assistant
    system-prompt-filePath to system prompt file. Takes precedence over system-prompt.""
    tokenToken value masked by the action. Defaults to github.token.github.token
    providerInference provider. Only copilot is supported.copilot
    copilot-cli-pathPath to Copilot CLI binary. If empty, uses copilot on PATH.""
    copilot-allow-toolsComma-separated list of --allow-tool values passed to Copilot CLI.""
  5. Use structured .prompt.yml files

    main

    When the prompt-file input points to a YAML file, the action uses a structured configuration. This allows you to define the model and template variables more robustly.

    Variables used in the prompt can be injected using the input and file_input parameters. The action parses these and merges them into the PromptConfig used to build the messages sent to the provider.

  6. Configure the AI Inference GitHub Action inputs

    main

    The ai-inference action uses several inputs to define the prompt, model, and provider. You can use either a structured .prompt.yml file or a legacy text-based format.

    Core Inputs

    • prompt-file: Path to the prompt file. If this is a YAML file (detected via isPromptYamlFile), the action uses the structured format.
    • prompt: (Legacy) The raw text prompt if not using a YAML file.
    • system-prompt-file: (Legacy) Path to a file containing the system prompt. Defaults to "You are a helpful assistant" if not provided.
    • model: The name of the model to use. If using a .prompt.yml file, the model key within that file takes precedence.
    • provider: The inference provider. Currently, only copilot is supported.
    • token: The authentication token. It defaults to the GITHUB_TOKEN environment variable if not explicitly provided.
    • copilot-cli-path: Path to the Copilot CLI executable.
    • copilot-allow-tools: A comma-separated list of tools to allow the model to use (e.g., tool1,tool2).

    Variable Inputs

    To support templating within your prompt files, you can provide variables via:

    • input: A string containing template variables.
    • file_input: A string containing file-based template variables.

    Variables provided in file_input will overwrite variables provided in input if there are collisions.

  7. Access model responses via outputs

    main

    The action provides two ways to access the model's response:

    1. response: The raw text of the model response.
    2. response-file: The path to a temporary file containing the response text. This is useful for large responses that might exceed shell command length limits.
    steps:
      - name: Run AI Inference
        id: inference
        uses: actions/ai-inference@v1
        with:
          prompt: Hello
    
      - name: Use Response File
        run: |
          echo "Response saved to: ${{ steps.inference.outputs.response-file }}"
          cat "${{ steps.inference.outputs.response-file }}"
  8. Load and parse a prompt YAML file

    main

    The loadPromptFile function is the primary way to ingest a prompt configuration. It performs the following steps:

    1. Reads the file from the provided filePath.
    2. Parses the YAML content into a PromptConfig object.
    3. Validates that the messages array exists and contains valid roles ('system', 'user', or 'assistant').
    4. Performs template variable substitution on all message contents using the provided templateVariables.

    Note: If no templateVariables are provided, it defaults to an empty object.

    const config = loadPromptFile('./my-prompt.prompt.yml', { user: 'Bob' });
    // config is now a fully parsed PromptConfig with variables replaced
  9. Parse template variables from file paths

    main

    The parseFileTemplateVariables function allows you to define template variables by mapping names to file paths in a YAML object. The function reads the content of each file and uses that content as the variable value.

    Example YAML input:

    context: ./docs/context.txt
    user_data: ./data/user.json

    Error Handling:

    • Throws an error if the input is not a valid YAML object.
    • Throws an error if a value is not a string (file path).
    • Throws an error if a specified file does not exist.
    • Throws an error if a file cannot be read.
    const fileInput = "my_var: ./path/to/file.txt";
    const variables = parseFileTemplateVariables(fileInput);
    // variables: { my_var: '[contents of file.txt]' }
  10. Extend inference with a custom `Spawner`

    main

    The copilotInference function accepts an optional spawner argument of type Spawner. This allows you to inject custom logic for how the CLI command is executed (e.g., for testing or using a different process execution library).

    Type Definition: type Spawner = (cmd: string, args: string[]) => Promise<RunResult>

    RunResult Shape:

    interface RunResult {
      stdout: string
      stderr: string
      exitCode: number | null
    }
    type Spawner = (cmd: string, args: string[]) => Promise<{ stdout: string; stderr: string; exitCode: number | null }>;
    
    // Example of a custom spawner
    const mySpawner: Spawner = async (cmd, args) => {
      // custom execution logic
      return { stdout: 'mock response', stderr: '', exitCode: 0 };
    };
    
    await copilotInference(request, mySpawner);
  11. Use template variables in prompts

    main

    You can inject dynamic data into your prompt files using the {{variable_name}} syntax. The replaceTemplateVariables function scans the text for these placeholders and replaces them with values provided in a TemplateVariables object.

    If a placeholder is found in the text but is missing from the provided variables, a warning is issued and the original {{placeholder}} is left intact in the text.

    const text = "Hello {{name}}, welcome to {{location}}!";
    const variables = { name: "Alice", location: "Wonderland" };
    
    const result = replaceTemplateVariables(text, variables);
    // result: "Hello Alice, welcome to Wonderland!"