How to Add Support for a New AI Agent to the agentsview Parser
To add a new AI agent to agentsview, define a constant in types.go, implement discovery and parsing functions in a new file under internal/parser/, and register the agent in the global Registry slice with metadata including environment variables and directory paths.
The agentsview project (available at kenn-io/agentsview) provides a unified interface for indexing and searching AI coding sessions from multiple agents. It uses a registry-based architecture where each agent is defined by a structured configuration that tells the core system how to locate, watch, and parse session files.
Understanding the Agent Registry Architecture
The parser subsystem relies on a central registry defined in internal/parser/types.go. Each entry is an AgentDef struct that maps an agent type to its filesystem behavior and parsing logic.
The registry entry specifies:
- Type: A constant identifying the agent (e.g.,
AgentMyAgent) - DisplayName: Human-readable name for UI rendering
- EnvVar/ConfigKey: Override mechanisms for the default directory path
- DefaultDirs: Standard locations where the agent stores sessions
- IDPrefix: namespace prefix for session IDs (e.g.,
myagent:) - DiscoverFunc: Function that walks directories and returns session files
- FindSourceFunc: Function that resolves a session ID to an absolute file path
Step-by-Step Implementation Guide
Step 1: Define the Agent Type Constant
Add a new constant to the AgentType enumeration in internal/parser/types.go. Place it alongside existing constants like AgentClaude, AgentAider, etc.
const (
AgentClaude AgentType = "claude"
AgentAider AgentType = "aider"
AgentMyAgent AgentType = "myagent" // your new agent
)
Step 2: Create the Parser Implementation
Create internal/parser/myagent.go (replace "myagent" with your agent's name). This file must implement three core functions:
Discovery Function: Walks the configured root directory and returns all session files.
func DiscoverMyAgentSessions(root string) []DiscoveredFile {
var out []DiscoveredFile
_ = filepath.WalkDir(root, func(p string, d os.DirEntry, err error) error {
if err != nil || d.IsDir() {
return nil
}
if filepath.Ext(p) == ".jsonl" {
out = append(out, DiscoveredFile{Path: p})
}
return nil
})
return out
}
Source Resolution Function: Maps a raw session ID (without prefix) to its absolute file path.
func FindMyAgentSourceFile(root, rawID string) string {
// MyAgent stores sessions as <root>/<rawID>.jsonl
return filepath.Join(root, rawID+".jsonl")
}
Parsing Function: Reads the session file and returns a ParseResult containing ParsedSession and []ParsedMessage.
func ParseMyAgent(path string) (ParseResult, error) {
data, err := os.ReadFile(path)
if err != nil {
return ParseResult{}, err
}
var sess ParsedSession
var msgs []ParsedMessage
// Parse JSONL or other format
for _, line := range splitLines(data) {
var rec map[string]any
if err = json.Unmarshal([]byte(line), &rec); err != nil {
continue
}
// Populate sess and msgs based on rec...
}
sess.ID = extractIDFromPath(path)
sess.Agent = AgentMyAgent
return ParseResult{Session: sess, Messages: msgs}, nil
}
Step 3: Register the Agent in the Registry
In internal/parser/types.go, add an AgentDef entry to the Registry slice:
{
Type: AgentMyAgent,
DisplayName: "MyAgent",
EnvVar: "MYAGENT_DIR", // optional override
ConfigKey: "myagent_dirs", // config.toml key
DefaultDirs: []string{".myagent/sessions"},
IDPrefix: "myagent:",
WatchSubdirs: []string{"threads"}, // optional FS watch paths
ShallowWatch: false,
FileBased: true,
DiscoverFunc: DiscoverMyAgentSessions,
FindSourceFunc: FindMyAgentSourceFile,
},
Step 4: Handle Agent-Specific Logic
Most of the codebase uses generic loops over the Registry, but if your agent requires custom API behavior (e.g., a special push endpoint), add a case for AgentMyAgent in the relevant switch statements in internal/sync/engine.go or HTTP handlers.
Step 5: Test Your Implementation
Create internal/parser/myagent_test.go to verify your parser handles the file format correctly:
func TestParseMyAgent(t *testing.T) {
const sample = `{"role":"user","content":"hi"}
{"role":"assistant","content":"hello"}`
tmp := t.TempDir()
path := filepath.Join(tmp, "myagent:12345.jsonl")
require.NoError(t, os.WriteFile(path, []byte(sample), 0600))
res, err := ParseMyAgent(path)
require.NoError(t, err)
assert.Equal(t, "myagent:12345", res.Session.ID)
assert.Equal(t, 2, len(res.Messages))
}
Run the test suite with make test or go test ./... to ensure your code passes go vet, go fmt, and all assertions.
Step 6: Update Configuration and Documentation
Update config/example.toml to include the new configuration key:
[agents]
myagent_dirs = ["/path/to/myagent/sessions"]
Add documentation to the README explaining the new agent support and any environment variables users can set.
Key Files and Their Roles
internal/parser/types.go: Contains theAgentDefstruct and the globalRegistryslice. You must modify this to add your constant and registry entry.internal/parser/<agent>.go: HousesDiscoverFunc,FindSourceFunc, and the parsing logic specific to your agent's file format.internal/parser/<agent>_test.go: Unit tests verifying discovery, path resolution, and parsing correctness.internal/server/*: Uses the registry to configure file watchers and HTTP endpoints—typically requires no changes unless adding custom API behavior.config/example.toml: Reference configuration showing the newmyagent_dirskey.
Summary
- Define a new
AgentTypeconstant ininternal/parser/types.goto identify your agent. - Implement
DiscoverMyAgentSessions,FindMyAgentSourceFile, andParseMyAgentin a new file underinternal/parser/. - Register the agent by appending an
AgentDefto theRegistryslice with metadata includingEnvVar,DefaultDirs, and function pointers. - Test your implementation using Go's testing framework with temporary files and sample session data.
- Document the new agent in configuration examples and README files.
Once registered, agentsview automatically watches the specified directories, discovers new sessions via your DiscoverFunc, resolves IDs to files via FindSourceFunc, and indexes the parsed content into SQLite and PostgreSQL.
Frequently Asked Questions
What file format should the parser return?
The parser must return a ParseResult struct containing a ParsedSession and a slice of ParsedMessage objects. The session file format itself (JSONL, XML, binary) is up to the agent, but the ParseMyAgent function must extract standard fields like ID, Agent, Timestamp, Role, and Content to populate these structures.
Do I need to modify the server code to add a new agent?
Usually no. The server in internal/server/ iterates over the Registry slice generically to set up file watchers and HTTP handlers. You only need to modify server code if your agent requires unique API endpoints or special synchronization logic not covered by the standard AgentDef fields.
How does the file watcher detect new sessions?
The file watcher uses the WatchSubdirs field in your AgentDef to determine which subdirectories to monitor for filesystem events. When a new file appears in these paths, the server triggers your DiscoverFunc to identify it as a valid session and your FindSourceFunc to resolve it when requested by ID.
Can I override the default directory location for an agent?
Yes. Users can override DefaultDirs by setting the environment variable specified in EnvVar (e.g., MYAGENT_DIR) or by adding the corresponding ConfigKey (e.g., myagent_dirs) to their config.toml file. The core code checks these overrides before falling back to the default paths.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →