matimo-examples 0.1.0-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +36 -0
- package/LICENSE +21 -0
- package/README.md +525 -0
- package/agents/decorator-pattern-agent.ts +368 -0
- package/agents/factory-pattern-agent.ts +253 -0
- package/agents/langchain-agent.ts +146 -0
- package/edit/edit-decorator.ts +128 -0
- package/edit/edit-factory.ts +120 -0
- package/edit/edit-langchain.ts +272 -0
- package/execute/execute-decorator.ts +49 -0
- package/execute/execute-factory.ts +46 -0
- package/execute/execute-langchain.ts +163 -0
- package/gmail/README.md +345 -0
- package/gmail/gmail-decorator.ts +216 -0
- package/gmail/gmail-factory.ts +231 -0
- package/gmail/gmail-langchain.ts +201 -0
- package/package.json +58 -0
- package/postgres/README.md +188 -0
- package/postgres/postgres-decorator.ts +198 -0
- package/postgres/postgres-factory.ts +180 -0
- package/postgres/postgres-langchain.ts +213 -0
- package/postgres/postgres-with-approval.ts +250 -0
- package/read/read-decorator.ts +107 -0
- package/read/read-factory.ts +104 -0
- package/read/read-langchain.ts +253 -0
- package/search/search-decorator.ts +154 -0
- package/search/search-factory.ts +129 -0
- package/search/search-langchain.ts +215 -0
- package/slack/README.md +339 -0
- package/slack/slack-decorator.ts +245 -0
- package/slack/slack-factory.ts +226 -0
- package/slack/slack-langchain.ts +242 -0
- package/tsconfig.json +20 -0
- package/web/web-decorator.ts +52 -0
- package/web/web-factory.ts +70 -0
- package/web/web-langchain.ts +163 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { MatimoInstance, setGlobalMatimoInstance, tool } from '@matimo/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Example: Execute tool using @tool decorator pattern
|
|
5
|
+
* Demonstrates class-based tool execution with automatic decoration
|
|
6
|
+
*/
|
|
7
|
+
class CommandExecutor {
|
|
8
|
+
@tool('execute')
|
|
9
|
+
async runCommand(command: string, timeout?: number): Promise<unknown> {
|
|
10
|
+
// Decorator automatically intercepts and executes via Matimo
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@tool('execute')
|
|
15
|
+
async listDirectory(): Promise<unknown> {
|
|
16
|
+
// Decorator automatically intercepts and executes via Matimo
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function decoratorExample() {
|
|
22
|
+
// Set up decorator support with autoDiscover
|
|
23
|
+
const matimo = await MatimoInstance.init({ autoDiscover: true });
|
|
24
|
+
setGlobalMatimoInstance(matimo);
|
|
25
|
+
|
|
26
|
+
console.info('=== Execute Tool - Decorator Pattern ===\n');
|
|
27
|
+
|
|
28
|
+
const executor = new CommandExecutor();
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
// Example 1: Run command through decorated method
|
|
32
|
+
console.info('1. Running command: echo "Hello from decorator"\n');
|
|
33
|
+
const result1 = await executor.runCommand('echo "Hello from decorator"');
|
|
34
|
+
console.info('Success:', (result1 as any).success);
|
|
35
|
+
console.info('Output:', (result1 as any).stdout);
|
|
36
|
+
console.info('---\n');
|
|
37
|
+
|
|
38
|
+
// Example 2: List directory
|
|
39
|
+
console.info('2. Running command: pwd\n');
|
|
40
|
+
const result2 = await executor.listDirectory();
|
|
41
|
+
console.info('Success:', (result2 as any).success);
|
|
42
|
+
console.info('Output:', (result2 as any).stdout);
|
|
43
|
+
console.info('---\n');
|
|
44
|
+
} catch (error: any) {
|
|
45
|
+
console.error('Error:', error.message);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
decoratorExample();
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { MatimoInstance } from '@matimo/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Example: Execute tool using factory pattern
|
|
5
|
+
* Demonstrates running shell commands and capturing output
|
|
6
|
+
*/
|
|
7
|
+
async function executeExample() {
|
|
8
|
+
// Initialize Matimo with autoDiscover to find all tools (core + providers)
|
|
9
|
+
const matimo = await MatimoInstance.init({ autoDiscover: true });
|
|
10
|
+
|
|
11
|
+
console.info('=== Execute Tool - Factory Pattern ===\n');
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
// Example 1: List files in current directory
|
|
15
|
+
console.info('1. Running: ls\n');
|
|
16
|
+
const lsResult = await matimo.execute('execute', {
|
|
17
|
+
command: 'ls',
|
|
18
|
+
timeout: 10000,
|
|
19
|
+
});
|
|
20
|
+
console.info('Success:', (lsResult as any).success);
|
|
21
|
+
console.info('Output:', (lsResult as any).stdout?.substring(0, 200));
|
|
22
|
+
console.info('---\n');
|
|
23
|
+
|
|
24
|
+
// Example 2: Get current working directory
|
|
25
|
+
console.info('2. Running: pwd\n');
|
|
26
|
+
const pwdResult = await matimo.execute('execute', {
|
|
27
|
+
command: 'pwd',
|
|
28
|
+
});
|
|
29
|
+
console.info('Success:', (pwdResult as any).success);
|
|
30
|
+
console.info('Output:', (pwdResult as any).stdout);
|
|
31
|
+
console.info('---\n');
|
|
32
|
+
|
|
33
|
+
// Example 3: Echo command
|
|
34
|
+
console.info('3. Running: echo "Hello from Matimo"\n');
|
|
35
|
+
const echoResult = await matimo.execute('execute', {
|
|
36
|
+
command: 'echo "Hello from Matimo"',
|
|
37
|
+
});
|
|
38
|
+
console.info('Success:', (echoResult as any).success);
|
|
39
|
+
console.info('Output:', (echoResult as any).stdout);
|
|
40
|
+
console.info('---\n');
|
|
41
|
+
} catch (error: any) {
|
|
42
|
+
console.error('Error executing command:', error.message);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
executeExample();
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ============================================================================
|
|
4
|
+
* EXECUTE TOOL - LANGCHAIN AI AGENT EXAMPLE
|
|
5
|
+
* ============================================================================
|
|
6
|
+
*
|
|
7
|
+
* PATTERN: True AI Agent with OpenAI + LangChain
|
|
8
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
9
|
+
* This is a REAL AI agent that:
|
|
10
|
+
* 1. Takes natural language user requests
|
|
11
|
+
* 2. Uses OpenAI LLM (GPT-4o-mini) to decide when to execute commands
|
|
12
|
+
* 3. Generates appropriate command parameters based on context
|
|
13
|
+
* 4. Executes tools autonomously
|
|
14
|
+
* 5. Processes results and responds naturally
|
|
15
|
+
*
|
|
16
|
+
* SETUP:
|
|
17
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
18
|
+
* 1. Create .env file:
|
|
19
|
+
* OPENAI_API_KEY=sk-xxxxxxxxxxxxx
|
|
20
|
+
*
|
|
21
|
+
* 2. Install dependencies:
|
|
22
|
+
* npm install
|
|
23
|
+
*
|
|
24
|
+
* USAGE:
|
|
25
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
26
|
+
* export OPENAI_API_KEY=sk-xxxx
|
|
27
|
+
* npm run execute:langchain
|
|
28
|
+
*
|
|
29
|
+
* ============================================================================
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import 'dotenv/config';
|
|
33
|
+
import { createAgent } from 'langchain';
|
|
34
|
+
import { ChatOpenAI } from '@langchain/openai';
|
|
35
|
+
import { MatimoInstance, convertToolsToLangChain, ToolDefinition } from '@matimo/core';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Run AI Agent with Execute tool
|
|
39
|
+
* The agent receives natural language requests and decides which commands to execute
|
|
40
|
+
*/
|
|
41
|
+
async function runExecuteAIAgent() {
|
|
42
|
+
console.info('\n╔════════════════════════════════════════════════════════╗');
|
|
43
|
+
console.info('║ Execute Tool AI Agent - LangChain + OpenAI ║');
|
|
44
|
+
console.info('║ True autonomous agent with LLM reasoning ║');
|
|
45
|
+
console.info('╚════════════════════════════════════════════════════════╝\n');
|
|
46
|
+
|
|
47
|
+
// Check required environment variables
|
|
48
|
+
const openaiKey = process.env.OPENAI_API_KEY;
|
|
49
|
+
if (!openaiKey) {
|
|
50
|
+
console.error('❌ Error: OPENAI_API_KEY not set in .env');
|
|
51
|
+
console.info(' Set it: export OPENAI_API_KEY="sk-..."');
|
|
52
|
+
console.info(' Get one from: https://platform.openai.com/api-keys');
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
console.info('🤖 Using OpenAI (GPT-4o-mini) as the AI agent\n');
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
// Initialize Matimo with auto-discovery
|
|
60
|
+
console.info('🚀 Initializing Matimo...');
|
|
61
|
+
const matimo = await MatimoInstance.init({ autoDiscover: true });
|
|
62
|
+
|
|
63
|
+
// Get execute tool
|
|
64
|
+
console.info('💬 Loading execute tool...');
|
|
65
|
+
const matimoTools = matimo.listTools();
|
|
66
|
+
const executeTools = matimoTools.filter((t) => t.name === 'execute');
|
|
67
|
+
console.info(`✅ Loaded ${executeTools.length} execute tool(s)\n`);
|
|
68
|
+
|
|
69
|
+
if (executeTools.length === 0) {
|
|
70
|
+
console.error('❌ Execute tool not found');
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Convert to LangChain tools using the built-in converter
|
|
75
|
+
const langchainTools = await convertToolsToLangChain(executeTools as ToolDefinition[], matimo);
|
|
76
|
+
|
|
77
|
+
// Initialize OpenAI LLM
|
|
78
|
+
console.info('🤖 Initializing OpenAI (GPT-4o-mini) LLM...');
|
|
79
|
+
const model = new ChatOpenAI({
|
|
80
|
+
modelName: 'gpt-4o-mini',
|
|
81
|
+
temperature: 0.7,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Create agent
|
|
85
|
+
console.info('🔧 Creating agent...\n');
|
|
86
|
+
const agent = await createAgent({
|
|
87
|
+
model,
|
|
88
|
+
tools: langchainTools as any,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Define agent tasks (natural language requests)
|
|
92
|
+
const userRequests = [
|
|
93
|
+
{
|
|
94
|
+
title: 'Example 1: Get system information',
|
|
95
|
+
request: 'Show me the current working directory using pwd command',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
title: 'Example 2: List files',
|
|
99
|
+
request: 'List files and directories in the current folder (use ls -la)',
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
title: 'Example 3: Create a test file',
|
|
103
|
+
request: 'Create a simple test file named test.txt in /tmp with content "Hello from Agent"',
|
|
104
|
+
},
|
|
105
|
+
];
|
|
106
|
+
|
|
107
|
+
console.info('🧪 Running AI Agent Tasks');
|
|
108
|
+
console.info('═'.repeat(60) + '\n');
|
|
109
|
+
|
|
110
|
+
// Run each task through the agent
|
|
111
|
+
for (const task of userRequests) {
|
|
112
|
+
console.info(`${task.title}`);
|
|
113
|
+
console.info('─'.repeat(60));
|
|
114
|
+
console.info(`👤 User: "${task.request}"\n`);
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
const response = await agent.invoke({
|
|
118
|
+
messages: [
|
|
119
|
+
{
|
|
120
|
+
role: 'user',
|
|
121
|
+
content: task.request,
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Get the last message from the agent
|
|
127
|
+
const lastMessage = response.messages[response.messages.length - 1];
|
|
128
|
+
if (lastMessage) {
|
|
129
|
+
const content =
|
|
130
|
+
typeof lastMessage.content === 'string'
|
|
131
|
+
? lastMessage.content
|
|
132
|
+
: String(lastMessage.content);
|
|
133
|
+
|
|
134
|
+
if (content && content.trim()) {
|
|
135
|
+
console.info(`🤖 Agent: ${content}\n`);
|
|
136
|
+
} else {
|
|
137
|
+
console.info('🤖 Agent: (Command executed successfully)\n');
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
} catch (error) {
|
|
141
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
142
|
+
console.info(`⚠️ Agent error: ${errorMsg}\n`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
console.info('═'.repeat(60));
|
|
147
|
+
console.info('\n✨ AI Agent Examples Complete!\n');
|
|
148
|
+
console.info('Key Features:');
|
|
149
|
+
console.info(' ✅ Real LLM (OpenAI) decides which tools to use');
|
|
150
|
+
console.info(' ✅ Natural language requests, not API calls');
|
|
151
|
+
console.info(' ✅ LLM generates command parameters based on context');
|
|
152
|
+
console.info(' ✅ Agentic reasoning and decision-making\n');
|
|
153
|
+
} catch (error) {
|
|
154
|
+
console.error('❌ Error:', error instanceof Error ? error.message : String(error));
|
|
155
|
+
if (error instanceof Error && error.stack) {
|
|
156
|
+
console.error('Stack:', error.stack);
|
|
157
|
+
}
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Run the AI agent
|
|
163
|
+
runExecuteAIAgent().catch(console.error);
|
package/gmail/README.md
ADDED
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
# Gmail Tools - LangChain Integration Examples
|
|
2
|
+
|
|
3
|
+
Complete guide for using Matimo Gmail tools with LangChain and OpenAI for email automation and AI-driven agent workflows.
|
|
4
|
+
|
|
5
|
+
## 📋 Overview
|
|
6
|
+
|
|
7
|
+
This directory contains three patterns for integrating Gmail tools with LangChain:
|
|
8
|
+
|
|
9
|
+
1. **Factory Pattern** (`gmail-factory.ts`) - Direct tool execution with explicit parameters
|
|
10
|
+
2. **Decorator Pattern** (`gmail-decorator.ts`) - TypeScript decorators with automatic auth injection
|
|
11
|
+
3. **AI Agent** (`gmail-langchain.ts`) - OpenAI-powered agent that decides which tools to use
|
|
12
|
+
|
|
13
|
+
All patterns use **Matimo's YAML-based tool definitions** and **automatic authentication token injection**.
|
|
14
|
+
|
|
15
|
+
## 🔐 Step 1: Get OAuth2 Access Token
|
|
16
|
+
|
|
17
|
+
### Using Google OAuth Playground (Easiest)
|
|
18
|
+
|
|
19
|
+
1. **Visit** [Google OAuth Playground](https://developers.google.com/oauthplayground)
|
|
20
|
+
|
|
21
|
+
2. **Configure OAuth Credentials** (top-right ⚙️ settings):
|
|
22
|
+
- ☑️ Check "Use your own OAuth credentials"
|
|
23
|
+
- Enter your OAuth **Client ID** (from [Google Cloud Console](https://console.cloud.google.com))
|
|
24
|
+
- Enter your OAuth **Client Secret**
|
|
25
|
+
|
|
26
|
+
> **Don't have credentials?** [Create them here](https://console.cloud.google.com/apis/credentials)
|
|
27
|
+
|
|
28
|
+
3. **Select Gmail API Scopes** (left panel):
|
|
29
|
+
|
|
30
|
+
Select based on what you need:
|
|
31
|
+
```
|
|
32
|
+
✅ https://www.googleapis.com/auth/gmail.readonly
|
|
33
|
+
(Read emails - needed for list-messages)
|
|
34
|
+
|
|
35
|
+
✅ https://www.googleapis.com/auth/gmail.send
|
|
36
|
+
(Send emails - needed for send-email)
|
|
37
|
+
|
|
38
|
+
✅ https://www.googleapis.com/auth/gmail.compose
|
|
39
|
+
(Create drafts - needed for create-draft)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
4. **Authorize**:
|
|
43
|
+
- Click "Authorize APIs"
|
|
44
|
+
- Grant permission in the popup
|
|
45
|
+
- Copy the generated **Access Token** (long string starting with `ya29.a0...`)
|
|
46
|
+
|
|
47
|
+
### Example Token
|
|
48
|
+
```
|
|
49
|
+
ya29.a0AfH6SMBx1234567890abcdefghijklmnopqrstuvwxyz...
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## 🔑 Step 2: Set Environment Variables
|
|
53
|
+
|
|
54
|
+
### Option A: Using `.env` file (Recommended)
|
|
55
|
+
|
|
56
|
+
1. **Create `.env` file** in this directory:
|
|
57
|
+
```bash
|
|
58
|
+
cd examples/tools/gmail
|
|
59
|
+
cat > .env << EOF
|
|
60
|
+
GMAIL_ACCESS_TOKEN=ya29.a0AfH6SMBx...your-token-here...
|
|
61
|
+
OPENAI_API_KEY=sk-...your-openai-key...
|
|
62
|
+
EOF
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
2. **Verify the file** exists:
|
|
66
|
+
```bash
|
|
67
|
+
cat .env
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Option B: Using Environment Variables Directly
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
export GMAIL_ACCESS_TOKEN="ya29.a0AfH6SMBx...your-token-here..."
|
|
74
|
+
export OPENAI_API_KEY="sk-...your-openai-key..."
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Option C: Using `.env.example` Template
|
|
78
|
+
|
|
79
|
+
Copy the template and add your values:
|
|
80
|
+
```bash
|
|
81
|
+
cp .env.example .env
|
|
82
|
+
# Then edit .env with your actual tokens
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## 🧪 Step 3: Test the Examples
|
|
86
|
+
|
|
87
|
+
### Prerequisites
|
|
88
|
+
```bash
|
|
89
|
+
# Install dependencies (if not already done)
|
|
90
|
+
cd /Users/sajesh/My\ Work\ Directory/matimo/examples/tools
|
|
91
|
+
pnpm install
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Run Factory Pattern
|
|
95
|
+
Tests direct tool execution with factory initialization:
|
|
96
|
+
```bash
|
|
97
|
+
pnpm run gmail:factory --email:youremail@gmail.com
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**What it does:**
|
|
101
|
+
- ✅ Lists recent emails (5 most recent)
|
|
102
|
+
- ✅ Sends test email to your address
|
|
103
|
+
- ✅ Creates a draft email
|
|
104
|
+
|
|
105
|
+
**Expected Output:**
|
|
106
|
+
```
|
|
107
|
+
📬 Example 1: List Your Recent Messages
|
|
108
|
+
✅ Found 5 recent messages:
|
|
109
|
+
1. From: Alice <alice@example.com>
|
|
110
|
+
2. From: Bob <bob@example.com>
|
|
111
|
+
...
|
|
112
|
+
|
|
113
|
+
📧 Example 2: Send Email
|
|
114
|
+
✅ Email sent successfully!
|
|
115
|
+
|
|
116
|
+
✏️ Example 3: Create Draft
|
|
117
|
+
✅ Draft created successfully!
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Run Decorator Pattern
|
|
121
|
+
Tests TypeScript decorator-based tool calling:
|
|
122
|
+
```bash
|
|
123
|
+
pnpm run gmail:decorator --email:youremail@gmail.com
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**What it does:**
|
|
127
|
+
- ✅ Lists messages via `@tool` decorator
|
|
128
|
+
- ✅ Sends email using decorated method
|
|
129
|
+
- ✅ Creates draft via decorator
|
|
130
|
+
|
|
131
|
+
**Key Feature:** Auto-injects `GMAIL_ACCESS_TOKEN` from environment
|
|
132
|
+
|
|
133
|
+
### Run AI Agent (Recommended)
|
|
134
|
+
Tests OpenAI-powered agent that decides which tools to use:
|
|
135
|
+
```bash
|
|
136
|
+
pnpm run gmail:langchain --email:youremail@gmail.com
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**What it does:**
|
|
140
|
+
- ✅ **Example 1:** Agent analyzes your email count
|
|
141
|
+
- ✅ **Example 2:** Agent sends email autonomously
|
|
142
|
+
- ✅ **Example 3:** Agent creates professionally-written draft
|
|
143
|
+
|
|
144
|
+
**Key Features:**
|
|
145
|
+
- 🤖 OpenAI GPT-4o-mini decides which tool to call
|
|
146
|
+
- 📝 Natural language requests (not API calls)
|
|
147
|
+
- 💭 LLM generates appropriate parameters
|
|
148
|
+
- 🔄 Multi-step agentic reasoning
|
|
149
|
+
|
|
150
|
+
**Example Interaction:**
|
|
151
|
+
```
|
|
152
|
+
Example 2: Send a test email
|
|
153
|
+
────────────────────────────────────
|
|
154
|
+
👤 User: "Please send a test email to vsajeshnair@gmail.com
|
|
155
|
+
with subject 'Hello from AI Agent' and body '...'"
|
|
156
|
+
|
|
157
|
+
🤖 Agent: The test email has been successfully sent to
|
|
158
|
+
**vsajeshnair@gmail.com** with the subject "Hello
|
|
159
|
+
from AI Agent"...
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## 🛠️ Troubleshooting
|
|
163
|
+
|
|
164
|
+
### Error: `GMAIL_ACCESS_TOKEN not set`
|
|
165
|
+
**Solution:** Set the environment variable:
|
|
166
|
+
```bash
|
|
167
|
+
export GMAIL_ACCESS_TOKEN="ya29.a0AfH6SMBx..."
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Error: `401 Unauthorized` or `403 Forbidden`
|
|
171
|
+
**Solution:** Your token may be expired or have insufficient scopes
|
|
172
|
+
- Get a new token from [OAuth Playground](https://developers.google.com/oauthplayground)
|
|
173
|
+
- Ensure you selected all required scopes: `gmail.readonly`, `gmail.send`, `gmail.compose`
|
|
174
|
+
|
|
175
|
+
### Error: `400 Bad Request` with empty query params
|
|
176
|
+
**Solution:** This is fixed by Matimo's parameter encoding system - update if needed:
|
|
177
|
+
```bash
|
|
178
|
+
cd /Users/sajesh/My\ Work\ Directory/matimo
|
|
179
|
+
pnpm build
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Error: `Email not actually sent/drafted`
|
|
183
|
+
**Solution:** Verify the OAuth token has been refreshed and scopes are correct. The email should appear in:
|
|
184
|
+
- **Sent folder** for `gmail-send-email`
|
|
185
|
+
- **Drafts folder** for `gmail-create-draft`
|
|
186
|
+
|
|
187
|
+
## 📚 Understanding the Patterns
|
|
188
|
+
|
|
189
|
+
### 1. Factory Pattern (`gmail-factory.ts`)
|
|
190
|
+
Direct SDK usage with explicit parameter passing:
|
|
191
|
+
```typescript
|
|
192
|
+
await matimo.execute('gmail-send-email', {
|
|
193
|
+
to: userEmail,
|
|
194
|
+
subject: 'Hello',
|
|
195
|
+
body: 'Message',
|
|
196
|
+
// GMAIL_ACCESS_TOKEN auto-injected from env
|
|
197
|
+
});
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**Use when:** You know exactly what parameters to pass
|
|
201
|
+
|
|
202
|
+
### 2. Decorator Pattern (`gmail-decorator.ts`)
|
|
203
|
+
TypeScript decorators for clean syntax:
|
|
204
|
+
```typescript
|
|
205
|
+
@tool('gmail-send-email')
|
|
206
|
+
async sendEmail(to: string, subject: string, body: string) {
|
|
207
|
+
// Matimo intercepts, auto-injects token
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
await agent.sendEmail(userEmail, 'Hello', 'Message');
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**Use when:** Building decorator-based agents or frameworks
|
|
215
|
+
|
|
216
|
+
### 3. AI Agent Pattern (`gmail-langchain.ts`)
|
|
217
|
+
OpenAI agent that reasons about tools:
|
|
218
|
+
```typescript
|
|
219
|
+
const agent = await createAgent({
|
|
220
|
+
model: new ChatOpenAI({ modelName: 'gpt-4o-mini' }),
|
|
221
|
+
tools: langchainTools,
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
await agent.invoke({
|
|
225
|
+
messages: [{
|
|
226
|
+
role: 'user',
|
|
227
|
+
content: 'Send me a test email'
|
|
228
|
+
}]
|
|
229
|
+
});
|
|
230
|
+
// Agent decides which tool to use and calls it!
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Use when:** Building autonomous AI agents with natural language
|
|
234
|
+
|
|
235
|
+
## 🔄 How Authentication Works
|
|
236
|
+
|
|
237
|
+
All three patterns use **Matimo's automatic auth injection**:
|
|
238
|
+
|
|
239
|
+
1. **Tool Definition** declares auth requirement in YAML:
|
|
240
|
+
```yaml
|
|
241
|
+
authentication:
|
|
242
|
+
type: oauth2
|
|
243
|
+
provider: google
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
2. **Execution Config** references auth parameter:
|
|
247
|
+
```yaml
|
|
248
|
+
execution:
|
|
249
|
+
headers:
|
|
250
|
+
Authorization: "Bearer {GMAIL_ACCESS_TOKEN}"
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
3. **Matimo auto-injects** from environment:
|
|
254
|
+
```typescript
|
|
255
|
+
// No explicit token passing needed!
|
|
256
|
+
await matimo.execute('gmail-send-email', {
|
|
257
|
+
to: 'user@example.com',
|
|
258
|
+
subject: 'Hello',
|
|
259
|
+
body: 'Message'
|
|
260
|
+
// GMAIL_ACCESS_TOKEN auto-added from process.env
|
|
261
|
+
});
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
This keeps your code clean and secure - no tokens in source code!
|
|
265
|
+
|
|
266
|
+
## 📦 What Gets Created
|
|
267
|
+
|
|
268
|
+
### Emails Sent
|
|
269
|
+
- Appear in your **Gmail Sent folder** immediately
|
|
270
|
+
- Subject: Varies per example
|
|
271
|
+
- From: Your configured Gmail account
|
|
272
|
+
|
|
273
|
+
### Drafts Created
|
|
274
|
+
- Appear in your **Gmail Drafts folder**
|
|
275
|
+
- Ready to edit and send manually
|
|
276
|
+
- Useful for AI-generated content review
|
|
277
|
+
|
|
278
|
+
### Messages Listed
|
|
279
|
+
- Shows your 5 most recent emails
|
|
280
|
+
- Displays sender, subject, and snippet
|
|
281
|
+
- No modifications to existing emails
|
|
282
|
+
|
|
283
|
+
## 🔗 Related Resources
|
|
284
|
+
|
|
285
|
+
- **[Matimo Documentation](https://tallclub.github.io/matimo/api-reference/SDK.html)** - Complete SDK reference
|
|
286
|
+
- **[Gmail API Docs](https://developers.google.com/gmail/api)** - Official Gmail API
|
|
287
|
+
- **[OAuth Playground](https://developers.google.com/oauthplayground)** - Get tokens
|
|
288
|
+
- **[Google Cloud Console](https://console.cloud.google.com)** - Manage credentials
|
|
289
|
+
- **[LangChain Docs](https://js.langchain.com/)** - LangChain reference
|
|
290
|
+
|
|
291
|
+
## 💡 Tips & Tricks
|
|
292
|
+
|
|
293
|
+
### Refresh Tokens
|
|
294
|
+
Tokens expire after 1 hour. Get a new one from OAuth Playground:
|
|
295
|
+
```bash
|
|
296
|
+
# Get fresh token
|
|
297
|
+
export GMAIL_ACCESS_TOKEN="ya29.a0AfH6SMBx...new-token..."
|
|
298
|
+
|
|
299
|
+
# Re-run example
|
|
300
|
+
pnpm run gmail:langchain --email:youremail@gmail.com
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Test with Different Emails
|
|
304
|
+
```bash
|
|
305
|
+
# Send to a different recipient
|
|
306
|
+
pnpm run gmail:factory --email:different@example.com
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Run All Three Patterns
|
|
310
|
+
```bash
|
|
311
|
+
echo "Factory Pattern:"
|
|
312
|
+
pnpm run gmail:factory --email:youremail@gmail.com
|
|
313
|
+
|
|
314
|
+
echo -e "\nDecorator Pattern:"
|
|
315
|
+
pnpm run gmail:decorator --email:youremail@gmail.com
|
|
316
|
+
|
|
317
|
+
echo -e "\nAI Agent Pattern:"
|
|
318
|
+
pnpm run gmail:langchain --email:youremail@gmail.com
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### View Generated Emails
|
|
322
|
+
1. Open Gmail: https://gmail.com
|
|
323
|
+
2. Check **Sent folder** for sent emails
|
|
324
|
+
3. Check **Drafts folder** for created drafts
|
|
325
|
+
4. Check **Inbox** for received emails
|
|
326
|
+
|
|
327
|
+
## ✨ Key Principles
|
|
328
|
+
|
|
329
|
+
✅ **All tools defined in YAML** - No code changes needed to modify tools
|
|
330
|
+
✅ **Auth tokens auto-injected** - Matimo reads from environment
|
|
331
|
+
✅ **Framework-agnostic** - Works with LangChain, CrewAI, custom agents
|
|
332
|
+
✅ **Stateless** - Matimo doesn't store tokens or state
|
|
333
|
+
✅ **Scalable** - Same pattern works for 10,000+ tools
|
|
334
|
+
|
|
335
|
+
## ❓ Questions or Issues?
|
|
336
|
+
|
|
337
|
+
1. Check the error message carefully
|
|
338
|
+
2. Verify your OAuth token is valid (less than 1 hour old)
|
|
339
|
+
3. Ensure all Gmail scopes are selected
|
|
340
|
+
4. Check that `GMAIL_ACCESS_TOKEN` is set correctly
|
|
341
|
+
5. Review the [main README](https://github.com/tallclub/matimo) for general setup
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
**Happy emailing! 📧** Use these patterns to build powerful, autonomous email agents with Matimo and OpenAI.
|