Deterministic context injection for AI agent workspaces. Analyzes workspace structure and injects task-aware instruction files (.github/instructions/*.md) so agents get high-quality guidance without wasting context tokens on framework tutorials or style conventions they already know.
agent-context is a lightweight system that bridges workspace analysis, tool profile management, and instruction generation. It ensures Copilot agents working on projects have access to:
- Workspace-specific instructions — detected languages, frameworks, test/build commands
- Tool profiles — MCP servers and custom agents available for that project
- Skill bundles — collections of MCP servers, templates, agents, and environment variables
- Completion guidance — checklists that address top failure modes (incomplete work, placeholder content, missing tests)
Analysis of agent failures showed they consistently:
- ✗ Leave work incomplete (declare done at 30-60%)
- ✗ Leave placeholder content (
[INSERT X],TODO) - ✗ Reference non-existent files in documentation
- ✗ Forget to run tests before committing
Traditional style guides don't help — agents already know Python/JS conventions. agent-context solves this by injecting task-aware, workspace-specific guidance in ~670 tokens.
┌─────────────────────────────────────────────────────────────┐
│ Workspace │
│ (Python/JS/Docker/K8s files, pyproject.toml, package.json) │
└────────────────────┬────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Analyzer │
│ - Detects languages, frameworks │
│ - Finds test runners, build/lint commands │
│ - Discovers source/test directories │
│ Output: WorkspaceInfo dataclass │
└────────────────────┬────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Renderer │
│ - Loads Jinja2 templates (4 template files) │
│ - Renders workspace-aware instruction files │
│ - Includes task context (task_id, feedback, criteria) │
│ Output: Dict[filename → content] │
└────────────────────┬────────────────────────────────────────┘
│
┌────────────┼────────────┐
▼ ▼ ▼
[Templates] [Profiles] [SkillBundles]
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Injector │
│ - Writes instruction files to .github/instructions/ │
│ (except copilot-instructions.md → .github/) │
│ - Generates mcp-config.json (if profile specified) │
│ Output: {filename → "written"|"skipped"|"error"} │
└─────────────────────────────────────────────────────────────┘
│ │
▼ ▼
[.instructions.md] [mcp-config.json]
files in workspace (MCP server config)
The analyzer detects:
- Languages: Python, JavaScript/TypeScript, Go, Java, Rust
- Frameworks: Django, FastAPI, Flask, React, Vue, Next.js, etc.
- Test runners: pytest, jest, vitest, go test, cargo test, maven test
- Build/lint commands: from pyproject.toml, package.json, Cargo.toml, go.mod
- Infrastructure: Dockerfile, K8s manifests, GitHub Actions workflows
- Source/test directories: src/, tests/, test/, tests/, etc.
Four templates are rendered and injected into .github/instructions/ (except copilot-instructions.md which goes to .github/):
| File | Condition | Tokens | Purpose |
|---|---|---|---|
safety.instructions.md |
Always | ~60 | Banned files, safety rules |
git-workflow.instructions.md |
Always | ~90 | Branch naming, commit format, PR workflow |
testing.instructions.md |
Test runner detected | ~170 | How to run tests, import patterns |
copilot-instructions.md |
Always | ~350 | Completion checklist, workspace context |
Profiles define which MCP servers and custom agents are available for a project. Built-in profiles:
| Profile | MCP Servers | Use Case |
|---|---|---|
base |
None | General development, no specialized tools |
oncall |
icm, ado-afd, adx, msdocs, enghub | Incident investigation and resolution |
azure |
ado, adx, msdocs | Azure infrastructure and services |
docs |
msdocs, enghub, context7 | Documentation and knowledge base |
Each profile is a ToolProfile containing:
name: Profile identifiermcp_servers: List of MCPServer configs (command, args, env, tools_filter)custom_agents: List of agent names (reserved for future use)env_vars: Dict of environment variables
Collections of related tools, agents, templates, and environment variables. Key bundles:
| Bundle | Servers | Agents | Purpose |
|---|---|---|---|
oncall |
icm, ado-afd, adx, msdocs, enghub | — | Incident investigation |
azure-dev |
ado, adx, msdocs | — | Azure development |
web-dev |
msdocs, enghub, context7 | — | Web development & docs |
testing |
— | — | Test runner & coverage rules |
Bundles can be composed with compose_bundles(bundle_names...) to merge MCP servers, agents, and environment variables.
The profiles.yaml file maps projects to tool profiles:
projects:
my-project:
profile: oncall
description: On-call incident management
data-pipeline:
profile: azure
description: Azure data infrastructureUsed by ProjectProfileRegistry to:
- Map project names to profiles
- Load available MCP servers for a project
- Generate
mcp-config.jsonfor Copilot CLI
python -m agent_context inject /workspaceAnalyzes workspace, renders templates, writes to .github/instructions/.
python -m agent_context inject /workspace \
--task-id fix-auth \
--task-desc "Add JWT token refresh" \
--feedback "Missing error handling for expired tokens"Task context is rendered into instruction templates, helping agents understand what's expected.
python -m agent_context inject /workspace \
--profile oncallGenerates mcp-config.json in workspace with MCP server configurations from the oncall profile.
python -m agent_context inject /workspace \
--task-id ctx-readme-update \
--task-desc "Rewrite README with architecture, examples, docs" \
--acceptance-criteria "Cover all features, add architecture diagram" \
--feedback "Critical: missing agent manifests, no architecture diagram" \
--profile base \
--overwriteinject WORKSPACE [options]
--task-id TEXT Task identifier
--task-desc TEXT Task description
--acceptance-criteria TEXT What must be done
--feedback TEXT Previous review feedback
--project-id TEXT Project identifier
--profile {base|oncall|azure|docs} Tool profile name
--overwrite Overwrite existing instruction files
--verbose, -v Debug logging
from agent_context import inject
status = inject("/workspace")
print(status)
# {
# "safety.instructions.md": "written",
# "git-workflow.instructions.md": "written",
# "testing.instructions.md": "written",
# "copilot-instructions.md": "written"
# }from agent_context import inject
task_context = {
"task_id": "fix-auth",
"description": "Add JWT token refresh endpoint",
"feedback": "Missing error handling for expired tokens",
"acceptance_criteria": "Handle refresh failures gracefully"
}
status = inject("/workspace", task_context=task_context)from agent_context import inject
status = inject("/workspace", profile_name="oncall")
if "mcp_config_path" in status:
print(f"MCP config written to: {status['mcp_config_path']}")from agent_context import get_profile, BUILTIN_PROFILES
# Get a specific profile
oncall_profile = get_profile("oncall")
print(f"MCP servers: {[s.name for s in oncall_profile.mcp_servers]}")
# List all profiles
print("Available profiles:", list(BUILTIN_PROFILES.keys()))from agent_context import (
get_bundle,
list_bundle_names,
compose_bundles
)
# Get a single bundle
oncall = get_bundle("oncall")
print(f"Servers: {[s.name for s in oncall.mcp_servers]}")
# List all bundles
print("Available bundles:", list_bundle_names())
# Compose multiple bundles
combined = compose_bundles("oncall", "azure-dev")
print(f"Combined servers: {[s.name for s in combined.mcp_servers]}")from agent_context.profile_loader import ProjectProfileRegistry
# Load from profiles.yaml
registry = ProjectProfileRegistry.from_file("profiles.yaml")
# Get profile for a project
profile = registry.get_project_profile("my-project")
if profile:
print(f"Project uses: {profile.name}")
print(f"MCP servers: {[s.name for s in profile.mcp_servers]}")
# List all projects
print("Projects:", registry.list_projects())
# See which profiles are used
print("Profiles in use:", registry.list_profiles_used())Tool profiles define available MCP servers and agents for a project.
@dataclass
class ToolProfile:
name: str # e.g., "oncall", "azure", "base"
mcp_servers: list[MCPServer] = [] # MCP server configurations
custom_agents: list[str] = [] # Agent names (reserved for future use)
env_vars: dict[str, str] = {} # Environment variables@dataclass
class MCPServer:
name: str # e.g., "icm", "ado-afd", "adx"
command: str # e.g., "mcp-icm"
args: list[str] = [] # Arguments to command
env: dict[str, str] = {} # Server-specific env vars
tools_filter: Optional[list[str]] = None # Only expose these tools (reserved for future use)from agent_context import MCPServer, ToolProfile
oncall_profile = ToolProfile(
name="oncall",
mcp_servers=[
MCPServer(
name="icm",
command="mcp-icm",
args=[],
env={"ICM_API": "https://api.icm.microsoft.com"},
),
MCPServer(
name="ado-afd",
command="mcp-ado-afd",
args=["--verbose"],
env={},
),
],
custom_agents=[], # Reserved for future use
env_vars={"LOG_LEVEL": "DEBUG"},
)# Map projects to tool profiles
projects:
<project-name>:
profile: <profile-name> # base, oncall, azure, docs
description: <optional>
agent-context:
profile: base
description: Context injection system
incident-manager:
profile: oncall
description: On-call incident management
azure-data-lake:
profile: azure
description: Azure data infrastructureSkill bundles are collections of MCP servers, agents, templates, and environment variables.
@dataclass
class SkillBundle:
name: str
description: str = ""
mcp_servers: list[MCPServer] = []
custom_agents: list[str] = []
instruction_templates: list[str] = [] # Reserved for future use
env_vars: dict[str, str] = {}from agent_context import SkillBundle, MCPServer
testing_bundle = SkillBundle(
name="testing",
description="Test execution and coverage guidelines",
mcp_servers=[],
custom_agents=[], # Reserved for future use
instruction_templates=[], # Reserved for future use
env_vars={"PYTHONPATH": "src/"},
)from agent_context import compose_bundles
# Merge multiple bundles
combined = compose_bundles("oncall", "azure-dev")
# Result: MCP servers from oncall + azure-dev agents + merged env_varsWhen you specify a --profile, agent-context generates mcp-config.json in the workspace root.
{
"mcpServers": {
"icm": {
"command": "mcp-icm",
"args": [],
"env": {}
},
"ado-afd": {
"command": "mcp-ado-afd",
"args": [],
"env": {}
}
},
"env": {
"LOG_LEVEL": "DEBUG"
}
}This file is read by Copilot CLI to enable MCP servers for agents.
# Generate mcp-config.json for oncall profile
python -m agent_context inject /workspace --profile oncall
# Result: creates or updates /workspace/mcp-config.jsonIn your K8s Job setup, inject instructions before running Copilot:
#!/bin/bash
export WORKSPACE=/workspace
export TASK_ID=fix-auth
export PROFILE=base
# 1. Inject workspace-aware instructions
python -m agent_context inject "$WORKSPACE" \
--task-id "$TASK_ID" \
--profile "$PROFILE" \
--verbose
# 2. Check status
if [ $? -ne 0 ]; then
echo "Instruction injection failed"
exit 1
fi
# 3. Run agent with Copilot CLI
PROMPT="Fix authentication error handling"
copilot -p "$PROMPT" --allow-all
# 4. Capture result
EXIT_CODE=$?
exit $EXIT_CODELists banned files and safety rules. Example:
# Safety Rules
Do NOT commit:
- API keys, credentials, secrets
- node_modules/, __pycache__/, .venv/
- Build artifacts (.o, .class, dist/)
- IDE settings (.idea/, .vscode/)
- Local config files (.env, config.local.json)Git workflow rules for the project. Example:
# Git Workflow
## Branch Naming
- Feature: feature/issue-123-description
- Bugfix: bugfix/issue-123-description
- Docs: docs/update-readme
## Commits
- Format: "type: description" (e.g., "feat: add JWT refresh")
- Sign: git commit -S -m "..."
## Pull Requests
- Title must reference issue: "Fix #123: description"
- Run tests before creating PR
- Link acceptance criteria in descriptionHow to run tests for the detected framework. Example:
# Testing
## Running Tests
python -m pytest tests/ -v # All tests
pytest tests/test_auth.py # Single file
pytest -k test_login # By name
## Before Committing
1. Run full test suite
2. Check code coverage (>80%)
3. Run linter: ruff check src/ tests/
4. Commit only if tests passMain guidance file. Contains:
- Detected workspace context (languages, frameworks, test runner)
- How to verify changes (test/lint commands)
- Completion checklist addressing top failure modes
- Task-specific guidance (if task context provided)
Example checklist:
# Completion Checklist
Before marking work complete, verify:
- ✓ All acceptance criteria met
- ✓ No placeholder text or TODO comments left
- ✓ Code changes tested (run: pytest tests/)
- ✓ New tests added for new functionality
- ✓ Documentation updated if APIs changed
- ✓ Git history is clean (proper commit messages)
- ✓ All files are saved and no debugging code leftgit clone https://github.com/YotamNordman/agent-context.git
cd agent-context
pip install -e .uv pip install -e .poetry install# Run all tests with pytest
uv run pytest tests/ -v
# Run specific test file
uv run pytest tests/test_analyzer.py -v
# Run with coverage
uv run pytest tests/ --cov=src/agent_context# Lint with ruff
uv run ruff check src/ tests/
# Format with ruff
uv run ruff format src/ tests/# Full injection
python -m agent_context inject /tmp/test-workspace \
--task-id test-task \
--profile oncall \
-v
# Check generated files
ls /tmp/test-workspace/.github/instructions/- Unit tests: 104 tests covering analyzer, injector, profiles, skills
- Integration tests: Profile loading, mcp-config generation
- Time: <1 second total
- Coverage: >90% of core logic
- ✗ Make LLM calls — pure file analysis + Jinja2 templating
- ✗ Enforce style guides — agents know Python/JS conventions
- ✗ Provide framework tutorials — only project-specific commands
- ✗ Handle orchestration — this is context injection, not task planning
- ✗ Create or define agent manifests — custom_agents is reserved for future use
Check that .github/instructions/ directory exists:
mkdir -p .github/instructions
python -m agent_context inject /workspace -vEnsure profile name is valid:
python -m agent_context inject /workspace --profile base -vRun with verbose logging to see what was detected:
python -m agent_context inject /workspace -vMIT