Skip to main content
Track agent conversations and browser recordings with commits. Metadata is stored as git notes and retrieved by commit SHA.

Why Use Agent Metadata?

When agents write code, you need to know:
  • What conversation led to each change – understand the context and intent
  • Which browser recording shows the agent working – replay the agent’s actions
  • How to reproduce or debug the agent’s decisions – retrace the logic
Storing this with commits means the context travels with the code. No separate database lookups—just use the commit SHA.

Quick Start

import { MorphClient } from '@morphllm/morphsdk';

const morph = new MorphClient({ apiKey: process.env.MORPH_API_KEY });

// Commit with agent metadata
const sha = await morph.git.commit({
  dir: './my-project',
  message: 'Implement user authentication',
  chatHistory: [
    { role: 'user', content: 'Add OAuth login' },
    { role: 'assistant', content: 'I will implement Google OAuth' }
  ],
  recordingId: 'rec_abc123'
});

// Retrieve metadata later
const metadata = await morph.git.getCommitMetadata({
  dir: './my-project',
  commitSha: sha
});

console.log(metadata?.chatHistory); // Chat messages
console.log(metadata?.recordingId); // Browser recording ID

Chat History

Store the full conversation that led to code changes. This is invaluable for:
  • Debugging why an agent made certain decisions
  • Continuing work in a new session with full context
  • Training and evaluating agent behavior

Format

Chat history follows the OpenAI/Anthropic message format:
interface ChatMessage {
  role: 'user' | 'assistant' | 'system';
  content: string;
  // Add any additional fields as needed
  name?: string;
  function_call?: any;
}

Example with Multi-Turn Conversation

await morph.git.commit({
  dir: './my-project',
  message: 'Add rate limiting middleware',
  chatHistory: [
    { 
      role: 'user', 
      content: 'We need to add rate limiting to the API' 
    },
    { 
      role: 'assistant', 
      content: 'I will add express-rate-limit middleware with Redis backing' 
    },
    { 
      role: 'user', 
      content: 'Set it to 100 requests per minute per IP' 
    },
    { 
      role: 'assistant', 
      content: 'Configuring rate limit: 100 req/min per IP with Redis store' 
    }
  ]
});
You can add any additional fields to chat messages. For example, include timestamp, model, or custom metadata fields for your agent framework.

Recording IDs

Link browser recordings to commits. Useful for:
  • Replaying agent interactions with web UIs
  • Debugging visual or interaction issues
  • Creating training data from agent sessions
await morph.git.commit({
  dir: './my-project',
  message: 'Fix login form validation',
  recordingId: 'rec_xyz789', // Your browser recording system's ID
  chatHistory: [
    { role: 'user', content: 'The login form allows empty passwords' },
    { role: 'assistant', content: 'Adding client-side validation' }
  ]
});
The recordingId can be any string identifier from your browser recording system (Playwright, Puppeteer, custom tooling, etc.).

Retrieving Metadata

Get metadata for any commit using its SHA:
const metadata = await morph.git.getCommitMetadata({
  dir: './my-project',
  commitSha: 'abc123def456...'
});

if (metadata) {
  console.log('Chat History:', metadata.chatHistory);
  console.log('Recording ID:', metadata.recordingId);
}

Use Cases

Resume agent session:
// Get last commit
const commits = await morph.git.log({ dir: './my-project', depth: 1 });
const lastSha = commits[0].oid;

// Get conversation history
const { chatHistory } = await morph.git.getCommitMetadata({
  dir: './my-project',
  commitSha: lastSha
});

// Continue conversation with full context
const response = await agent.chat([
  ...chatHistory,
  { role: 'user', content: 'Now add password reset functionality' }
]);
Audit trail:
// Get all commits in a date range
const commits = await morph.git.log({ dir: './my-project' });

for (const commit of commits) {
  const metadata = await morph.git.getCommitMetadata({
    dir: './my-project',
    commitSha: commit.oid
  });
  
  console.log(`Commit: ${commit.commit.message}`);
  console.log(`Recording: ${metadata?.recordingId}`);
  console.log(`Turns: ${metadata?.chatHistory?.length || 0}`);
}
Debug agent decisions:
// When a bug is found, trace back the conversation
const buggyCommit = 'abc123...';
const metadata = await morph.git.getCommitMetadata({
  dir: './my-project',
  commitSha: buggyCommit
});

// Replay the conversation to understand what went wrong
metadata.chatHistory.forEach(msg => {
  console.log(`${msg.role}: ${msg.content}`);
});

Storage Details

Agent metadata is stored as git notes, which means:
  • It travels with the repository when cloned
  • It doesn’t affect the commit history or SHA
  • It can be retrieved using just the commit SHA
  • It’s version controlled but separate from code
Git notes are stored in the refs/notes/morph namespace. They’re automatically pushed and pulled with your repository.

Integration Examples

OpenAI Agent

import OpenAI from 'openai';
import { MorphClient } from '@morphllm/morphsdk';

const openai = new OpenAI();
const morph = new MorphClient({ apiKey: process.env.MORPH_API_KEY });

const chatHistory = [];

// Agent loop
while (true) {
  const response = await openai.chat.completions.create({
    model: 'gpt-4',
    messages: chatHistory
  });
  
  chatHistory.push(response.choices[0].message);
  
  // Agent modifies code...
  
  // Commit with full history
  await morph.git.add({ dir: './project', filepath: '.' });
  await morph.git.commit({
    dir: './project',
    message: 'Agent changes',
    chatHistory
  });
  await morph.git.push({ dir: './project' });
}

Anthropic Agent

import Anthropic from '@anthropic-ai/sdk';
import { MorphClient } from '@morphllm/morphsdk';

const anthropic = new Anthropic();
const morph = new MorphClient({ apiKey: process.env.MORPH_API_KEY });

const chatHistory = [];

const response = await anthropic.messages.create({
  model: 'claude-3-5-sonnet-20241022',
  messages: chatHistory
});

chatHistory.push({
  role: 'assistant',
  content: response.content[0].text
});

// Commit with conversation
await morph.git.commit({
  dir: './project',
  message: 'Implement feature',
  chatHistory
});

Vercel AI SDK

import { generateText } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
import { MorphClient } from '@morphllm/morphsdk';

const morph = new MorphClient({ apiKey: process.env.MORPH_API_KEY });

const chatHistory = [];

const { text } = await generateText({
  model: anthropic('claude-3-5-sonnet-20241022'),
  messages: chatHistory
});

chatHistory.push({ role: 'assistant', content: text });

// Store conversation
await morph.git.commit({
  dir: './project',
  message: 'Agent changes',
  chatHistory
});