Perform evaluation, error analysis, and tuning

How you know an agent did the right thing, and what you change when it did not. Define success before the run, read the evidence the platform already produces, name the root cause precisely, and tune one layer at a time — instructions, memory or tools.

Skill 4 15–20% of the exam Skills measured: study guide revision of May 4, 2026
Three objectives in this skill area:

4.1 Define success criteria and evaluation signals

Specify expected outcomes and operational constraints

Evaluation starts before the agent runs. Write the criteria into the issue, reference them from the pull request, and validate against them. Alongside what must be true, state the operational constraints the work must respect:

ConstraintExample
ScopeOnly src/ and lockfiles; no workflow or infrastructure changes
Non-goalsNo refactoring beyond the fix; no new dependencies
QualityNo test deleted or skipped; coverage does not drop
SecurityNo new code scanning alerts; no secrets; no High/Critical dependency vulnerabilities
TimeFits one cloud agent session — the hard limit is 59 minutes
CostA cap on autopilot continuations or, in Agentic Workflows, max-ai-credits per run

Identify qualitative and quantitative signals

Quantitative — measurable, automatableQualitative — needs judgement
Required checks pass or fail · test pass rate and coverage delta · lint and type errors · new code scanning alerts · secret scanning hits · dependency review findings · number of iterations before green · session duration and AI credits consumed · PRs created versus merged and median time to merge (Copilot usage metrics) Does the change solve the actual problem? · review comments and requested changes · plan quality and adherence · fit with architecture and conventions · readability and maintainability · clarity of the PR description and evidence · whether the scope was respected

Quantitative signals scale and can be enforced as gates; qualitative ones catch what no check was written to detect. A healthy evaluation design uses both, and lets the quantitative gates remove the obvious failures so human reviewers spend their attention on the qualitative questions.

flowchart LR
  ISSUE["Issue<br/>task · acceptance criteria"] --> PR["Agent opens PR<br/>references the criteria"]
  PR --> RUNS["Workflows run<br/>build · test · lint · scans"]
  RUNS --> GATE["Required checks<br/>enforced by ruleset"]
  GATE --> REVIEW["Reviewer approves<br/>qualitative judgement"]
  REVIEW --> MERGE["Merge"]
The end-to-end evaluation flow: criteria in the issue, evidence from workflows, enforcement by required checks, judgement by a reviewer.

Align evaluation criteria with development intent

An evaluation that measures the wrong thing rewards the wrong behaviour. Criteria must describe the intent of the task, and each should map to a signal that can actually observe it.

Weak criterionAligned criterionSignal
"Tests pass""The vulnerable version is no longer resolvable, including transitively"Dependency alert closed; dependency review clean
"Add tests""Branch coverage of auth/ rises above 80%, with no test removed"Coverage report artifact; diff check on test files
"Fix the bug""Issue #312 reproduction case passes and is added as a regression test"New test in the PR; CI result
"Improve performance""p95 of /search under 200 ms in the benchmark job"Benchmark artifact compared with the base branch

Guard the gates themselves

An agent that is judged by tests can make them pass by weakening them. Treat edits to tests, CI workflows and required-check names as high-risk changes — route them to code owners and flag them in review. Renaming or removing a required check silently disables a gate: if checks drift, governance drifts.

Generate evaluation signals with automated scanning

GitHub's security tools produce objective signals that fit straight into a required-check model.

ToolSignalWhere it appears
Code scanning (CodeQL, or third-party SARIF uploads)Vulnerabilities and coding errors in changed codePR checks and annotations; Security tab; a ruleset can require code scanning results
Secret scanning and push protectionCredentials in code; push protection blocks supported secrets before they landAlerts; blocked pushes
Dependency reviewNew dependencies with known vulnerabilities or disallowed licencesPR check (fail on a severity threshold)
Dependabot alertsVulnerable dependencies already in the repositorySecurity tab; good agent task sources
Copilot code reviewAn AI second opinion on the diffReview comments on the PR
yaml
name: Security gates
on:
  pull_request:
    branches: [main]

permissions:
  contents: read

jobs:
  dependency-review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/dependency-review-action@v5
        with:
          fail-on-severity: high

  codeql:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      security-events: write
    steps:
      - uses: actions/checkout@v7
      - uses: github/codeql-action/init@v4
        with:
          languages: javascript-typescript
      - uses: github/codeql-action/analyze@v4

Cloud agent's built-in validation

Copilot cloud agent evaluates its own work before finishing, and tries to fix what it finds:

  • CodeQL checks the code it generated for security issues.
  • Newly added dependencies are checked against the GitHub Advisory Database for malware and for High or Critical CVSS vulnerabilities.
  • Secret scanning looks for API keys, tokens and other secrets.
  • Copilot code review gives it a second opinion.

This does not require a GitHub Secret Protection, Code Security or Advanced Security licence. Details appear in the session log, and a repository administrator can switch individual tools off under Settings → Copilot → Cloud agent → Validation tools — for example to avoid duplicating another security product. It is a first line of defence, not a replacement for your own required checks.

The agent's self-check is not the gate

Built-in validation makes the agent's output better; required status checks and reviews decide whether it merges. If a question asks how to guarantee that no PR with a new high-severity alert can merge, the answer is a ruleset requiring code scanning results or the CodeQL check — not the agent's built-in CodeQL pass.

4.2 Analyze agent failures and identify root causes

Identify failures with logs, plans, traces, outputs and artifacts

The first step is always to gather the evidence the platform already produced, then compare intent with results: intent lives in the issue and the plan; results live in the commits, outputs and logs.

EvidenceWhat it tells youWhere to find it
Cloud agent session logThe agent's reasoning, each tool call and its result, setup and MCP start-upAgents page; View session on the PR; the link in each commit
The planWhat the agent intended — compare with what it didPR description, planning session, plan.md
PR timeline and diffWhat changed, when, and in response to which commentThe pull request
Checks tab and workflow logsWhich gate failed, and howChecks tab; Actions tab
Uploaded artifactsDurable reports that outlive scrolled-away logsArtifacts section of the run
Firewall warningsBlocked outbound requests and the command that made themPR body or a comment
Hook logsTool calls allowed, denied or failed, with argumentsWherever your hooks write — sent over HTTP for cloud agent, whose filesystem is ephemeral
TracesSpans for each model call and tool callOpenTelemetry from the Copilot SDK and CLI
Audit logAgent actions across the organizationactor:Copilot filter, with agent_session_id

Classify root causes

flowchart TB
  START["Agent output is wrong or incomplete"] --> Q1{"Did it understand<br/>the task correctly?"}
  Q1 -->|"no — wrong goal, ignored criteria"| REASON["Reasoning error<br/>fix: instructions · criteria · plan-first"]
  Q1 -->|"yes"| Q2{"Did its tool calls<br/>succeed as intended?"}
  Q2 -->|"no — wrong command, misused workflow"| TOOL["Tool misuse<br/>fix: tool allowlist · skills · hooks"]
  Q2 -->|"yes"| Q3{"Was its information<br/>current and consistent?"}
  Q3 -->|"no — stale PR, conflicting docs"| CONTEXT["Context issue<br/>fix: single source of truth · update branch"]
  Q3 -->|"yes"| ENV["Environment issue<br/>fix: setup steps · firewall · secrets · runner"]
A quick decision path for classifying an agent failure before you try to fix it.
CategoryTypical symptomsUsual fix
Reasoning errorMisread requirements; wrong logic; acceptance criteria ignored; plausible but wrong solutionSharper acceptance criteria; plan-first review; clearer or more specific instructions; a narrower custom agent
Tool misuseWrong commands or scripts; misconfigured or untriggered workflows; the wrong MCP tool; destructive commands attemptedRestrict or re-scope tools; add a skill with the right procedure; a preToolUse hook to block misuse; fix workflow triggers
Context issueOutdated PR state; missing earlier decision; conflicting information across artifacts; stale memoryOne source of truth; update the branch; update the issue or PR; delete wrong memories
Environment issueMissing dependency or tool; blocked network request; missing secret; wrong runner OS; session timeout; ruleset blocking the pushcopilot-setup-steps.yml; firewall allowlist; Agents secrets; runner label; smaller tasks; bypass actor

Symptom first, not model first

"The model is bad" is almost never the root cause you can act on. A dependency the agent could not install is an environment issue; a test it deleted to make CI pass is a reasoning issue and a missing guardrail. Name the category, then fix the layer that owns it.

4.3 Tune agent behaviour based on evaluation results

flowchart LR
  RUN["Run the agent"] --> OBSERVE["Observe<br/>logs · traces · artifacts"]
  OBSERVE --> CLASSIFY["Classify<br/>the root cause"]
  CLASSIFY --> FIX["Fix one thing<br/>instructions · memory · tools"]
  FIX --> RERUN["Re-run and compare"]
  RERUN --> OBSERVE
Tuning is iterative: change one layer at a time, re-run, and compare with the previous evidence.

Revise instructions, workflows or constraints

  • Put build, test and validation commands in .github/copilot-instructions.md — an agent that can validate its own changes produces PRs that merge faster.
  • Add path-specific instructions where one area keeps going wrong, and say what to do when requirements are ambiguous.
  • Tighten a custom agent's prompt and description; split an over-broad agent into narrower ones.
  • Make tasks smaller, with explicit acceptance criteria and file directions; move risky work to plan-first.
  • Fix the workflow — triggers, required checks, a missing evidence upload.
markdown
# .github/copilot-instructions.md
This is a TypeScript monorepo using pnpm workspaces.

## Build and validate before every commit
- Install: pnpm install --frozen-lockfile
- Build:   pnpm -r build
- Test:    pnpm -r test   (all tests must pass; do not skip or delete tests)
- Lint:    pnpm lint

## Boundaries
- Never edit files under .github/workflows/ or infra/.
- Database migrations live in packages/db/migrations and are append-only.
- If a requirement is ambiguous, stop and ask in the PR instead of guessing.

Refine memory usage

  • Delete wrong or misleading Copilot Memory facts (repository owners, Settings → Copilot → Memory).
  • Move repeated corrections into instructions so they are authoritative and reviewed.
  • Remove conflicting instruction files and keep one source of truth per topic.
  • Update the issue or PR description when decisions change, so resumed sessions re-anchor correctly.

Refine tool usage and tool access

Evaluation findingTool-level change
Agent kept guessing how to install dependenciesDeterministic copilot-setup-steps.yml
Request to an internal registry was blockedAdd the host to the firewall custom allowlist
Agent used a write-capable MCP tool it did not needAllowlist only the read-only tools in the server's tools field
Reviewer agent edited codeRemove edit and execute from its profile's tools
Agent tried rm -rf or git push --forcepreToolUse hook denying the pattern; --deny-tool in CLI runs
Agent could not read Actions logs to debug CIEnable the GitHub MCP actions toolset, or add a debugging skill
Planning agent was slow and expensiveFewer tools means a smaller context; give it only read and search
yaml
- name: Summarize the agent run for reviewers
  if: always()
  run: |
    {
      echo "## Agent evaluation"
      echo "- Commit: ${{ github.sha }}"
      echo "- Tests: $(jq -r '.numPassedTests' results.json) passed, $(jq -r '.numFailedTests' results.json) failed"
      echo "- Coverage delta: $(cat coverage-delta.txt)"
    } >> "$GITHUB_STEP_SUMMARY"

- uses: actions/upload-artifact@v7
  if: always()
  with:
    name: evaluation-${{ github.run_id }}
    path: |
      results.json
      coverage/

Test agent changes before releasing them

Treat a profile change like a code change. Organizations can test a custom agent privately in the .github/agents folder of their .github-private repository, then release it by moving the profile to the root agents folder. Every tuning change should land through a pull request, so the history of why the agent behaves as it does stays reviewable. The lifecycle side of this is on the multi-agent page.