Skip to main content

Coding Agent

Norns includes a coding agent that can understand codebases and make changes. It supports reading files, searching code, editing files, running commands, and git operations.

Status

Enabled: As of RAV-136, the CodeDomainSupervisor is fully integrated with the NornsSupervisor and routes Domain.CODE operations.

Architecture

┌─────────────────────────────────────────────────────────────┐
│ NornsSupervisor │
│ (Intent classification → Domain.CODE) │
└─────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────┐
│ CodeDomainSupervisor │
│ LLM-based routing to appropriate workers │
│ Stores params in self._routing_params │
└─────────────────────────────────────────────────────────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ CodeRead │ │ CodeWrite │ │ CodeExecute │ │ CodeContext │
│ Worker │ │ Worker │ │ Worker │ │ Worker │
│ file_read │ │ file_write │ │ run_command │ │ analyze_ │
│ code_search │ │ file_edit │ │ git_* │ │ project │
│ list_files │ │ file_create │ │ run_tests │ │ register_ │
│ get_symbols │ │ │ │ run_build │ │ project │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
│ │ │ │
└──────────────┴──────────────┴──────────────┘


WorkerResult
(success, result, error)

Flow

  1. Intent Classification: NornsSupervisor classifies user message as Domain.CODE
  2. Supervisor Routing: CodeDomainSupervisor uses LLM to classify operation type and route to workers
  3. Worker Execution: Selected worker(s) execute with WorkerResult return type
  4. Result Synthesis: CodeDomainSupervisor combines results into coherent response

Key Files

FilePurpose
agents/domain_supervisors/code_supervisor.pyCodeDomainSupervisor implementation
agents/workers/code_workers.pyAll 4 worker implementations
agents/supervisor.pyNornsSupervisor with Domain.CODE routing
agents/base.pyBaseDomainSupervisor and BaseWorker interfaces

Workers

CodeReadWorker

Handles read-only code operations.

Operations:

  • file_read - Read file contents
  • code_search - Search for patterns using grep
  • list_files - List files in a directory with glob patterns
  • get_file_symbols - Extract functions, classes, and imports

Parameter Aliases:

  • directorypath (for list_files)
  • file_typepattern (e.g., "python" → "*.py")
async def execute(
self, state: HierarchicalState, action: str,
operation: str = "file_read",
file_path: Optional[str] = None,
path: Optional[str] = None,
directory: Optional[str] = None, # alias for path
pattern: Optional[str] = None,
file_type: Optional[str] = None, # alias for pattern
query: Optional[str] = None,
**kwargs,
) -> WorkerResult

CodeWriteWorker

Handles file modification operations.

Operations:

  • file_write - Write complete file contents
  • file_edit - Apply surgical edits
  • file_create - Create new files

CodeExecuteWorker

Runs allowed shell commands.

Operations:

  • run_command - Execute shell command
  • git_status - Get git status
  • git_diff - Get git diff
  • git_add - Stage files
  • git_commit - Create commit
  • run_tests - Run project tests
  • run_build - Build project

Allowed Commands:

  • Package managers: npm, yarn, pnpm, bun, pip, poetry
  • Test runners: pytest, jest, vitest, mocha
  • Build tools: make, cargo, go, tsc
  • Git operations: status, diff, add, commit, log, branch
  • Docker: docker, docker-compose
  • Utilities: ls, cat, head, tail, grep, find, tree

Blocked Patterns:

  • rm -rf /
  • Commands with ; rm, && rm, | rm
  • Redirects to /dev/
  • Piped curl/wget to shell

CodeContextWorker

Manages project understanding.

Operations:

  • analyze_project - Analyze project structure and tech stack
  • get_project_context - Get summary of project context
  • learn_pattern - Learn a code pattern for future reference
  • register_project - Register a new project for operations

Database Tables

code_projects

Registered code projects.

ColumnTypeDescription
project_idUUIDPrimary key
user_idUUIDOwner
nameVARCHAR(255)Project name
slugVARCHAR(100)URL-safe identifier
repo_typeVARCHAR(50)local, gitlab, github
repo_urlTEXTRemote URL
local_pathTEXTLocal filesystem path
primary_languageVARCHAR(50)Main language
allowed_commandsTEXT[]Permitted commands
blocked_pathsTEXT[]Restricted paths
is_activeBOOLEANWhether project is accessible

code_patterns

Learned code patterns for project context.

ColumnTypeDescription
pattern_idUUIDPrimary key
project_idUUIDParent project
pattern_nameVARCHAR(255)Pattern identifier
pattern_typeVARCHAR(50)function, class, config, test, etc.
pattern_contentTEXTPattern template/example
usage_countINTEGERHow often referenced

code_operations

Audit log of all code operations.

ColumnTypeDescription
operation_idUUIDPrimary key
user_idUUIDWho performed
project_idUUIDTarget project
operation_typeVARCHAR(50)read, write, execute
target_pathTEXTFile/directory affected
commandTEXTCommand executed (if applicable)
statusVARCHAR(50)success, failed, blocked

Security Model

Path Blocking

The following paths are blocked from read/write operations:

  • .env files
  • secrets/ directories
  • credentials files
  • .git/config
  • SSH keys (id_rsa, .ssh/)

Command Allowlist

Only explicitly allowed commands can be executed. The allowlist includes common development tools but excludes dangerous operations.

Audit Logging

All code operations are logged to the code_operations table with:

  • User who performed the operation
  • Target path
  • Operation type
  • Command executed (for execute operations)
  • Success/failure status

Usage Examples

Read a file

@norns Read the main.py file

List files

@norns List all Python files in /app

Search code

@norns Search for "async def" in the codebase

Run tests

@norns Run the tests for the auth module

Check git status

@norns What's the git status?

Analyze project

@norns Analyze the structure of this project

Routing Examples

The CodeDomainSupervisor uses LLM to classify operations:

User RequestWorkerOperationParams
"read main.py"code_readfile_readfile_path: "main.py"
"list python files in /app"code_readlist_filespath: "/app", pattern: "*.py"
"search for UserService"code_readcode_searchquery: "UserService"
"edit main.py to add logging"code_writefile_edit-
"run pytest"code_executerun_tests-
"git status"code_executegit_status-
"analyze this project"code_contextanalyze_project-

Implementation Notes

WorkerResult Pattern

All workers return WorkerResult with:

@dataclass
class WorkerResult:
worker_name: str
domain: Domain
success: bool
result: Optional[Any] = None
error: Optional[str] = None
metadata: Optional[dict] = None

Parameter Forwarding

The CodeDomainSupervisor:

  1. Uses LLM to parse operation type and parameters
  2. Stores params in self._routing_params
  3. Passes params to workers via **params

NornsSupervisor Integration

# In supervisor.py
self.domain_supervisors = {
Domain.CODE: CodeDomainSupervisor(),
# ... other domains
}

Testing

Smoke test commands:

# List files
curl -X POST http://docs/AI-ML-Platform/norns-agent:8000/api/chat \
-H "Content-Type: application/json" \
-d '{"messages":[{"role":"user","content":"list all python files in /app"}]}'

# Read file
curl -X POST http://docs/AI-ML-Platform/norns-agent:8000/api/chat \
-H "Content-Type: application/json" \
-d '{"messages":[{"role":"user","content":"read the file /app/main.py"}]}'

# Search code
curl -X POST http://docs/AI-ML-Platform/norns-agent:8000/api/chat \
-H "Content-Type: application/json" \
-d '{"messages":[{"role":"user","content":"search for CodeReadWorker in the codebase"}]}'