@areumtecnologia/autonomouscustomerserviceagent 2.0.1
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 +13 -0
- package/README.md +198 -0
- package/package.json +35 -0
- package/src/AgentConfig.js +31 -0
- package/src/AgentEvents.js +24 -0
- package/src/AgentManager.js +31 -0
- package/src/AgentSession.js +52 -0
- package/src/AutonomousCustomerServiceAgent.js +830 -0
- package/src/index.js +22 -0
- package/src/utils.js +55 -0
- package/tests/test-api-restful.js +104 -0
- package/tests/test.js +279 -0
package/.env.example
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Google Gemini API Configuration
|
|
2
|
+
GOOGLE_GEMINI_API_KEY=your-api-key-here
|
|
3
|
+
|
|
4
|
+
# Agent Configuration (Optional)
|
|
5
|
+
MODEL=gemma-4-26b-a4b-it
|
|
6
|
+
MAX_AGENTIC_LOOP_TURNS=8
|
|
7
|
+
SESSION_TTL=1800000
|
|
8
|
+
TURN_TIMEOUT_MS=90000
|
|
9
|
+
MAX_VULNERABILITY_ATTEMPTS=3
|
|
10
|
+
TEMPERATURE=0.2
|
|
11
|
+
TOP_P=0.95
|
|
12
|
+
THINKING_LEVEL=MINIMAL
|
|
13
|
+
MAX_OUTPUT_TOKENS=4096
|
package/README.md
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# Autonomous Customer Service Agent
|
|
2
|
+
|
|
3
|
+
Um agente autônomo de atendimento ao cliente baseado em IA, desenvolvido com Google Gemini, capaz de gerenciar múltiplas sessões, executar ferramentas customizadas e aplicar retry com backoff exponencial. Suporta modos de tratamento de indisponibilidade `async` e `sync` para garantir continuidade do atendimento.
|
|
4
|
+
|
|
5
|
+
## ✨ Características
|
|
6
|
+
|
|
7
|
+
- **Gerenciamento de Sessões**: TTL configurável com renovação automática por atividade
|
|
8
|
+
- **Agentic Loop Completo**: Suporte a tool calls com execução contextualizada
|
|
9
|
+
- **Retry com Backoff Exponencial**: Recuperação automática de falhas com jitter
|
|
10
|
+
- **Timeouts Granulares**: Por turno e por ferramenta via AbortController
|
|
11
|
+
- **Registro Programático de Ferramentas**: Schemas customizados + handlers
|
|
12
|
+
- **Detecção de Vulnerabilidades**: Rastreamento de tentativas de exploração
|
|
13
|
+
- **Eventos Estruturados**: EventEmitter para monitoramento completo
|
|
14
|
+
|
|
15
|
+
## 🚀 Quickstart
|
|
16
|
+
|
|
17
|
+
### Pré-requisitos
|
|
18
|
+
|
|
19
|
+
- Node.js 16+
|
|
20
|
+
- npm ou yarn
|
|
21
|
+
- Chave de API do Google Gemini
|
|
22
|
+
|
|
23
|
+
### Instalação
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Clone ou extraia o projeto
|
|
27
|
+
cd AutonomousCustomerServiceAgent
|
|
28
|
+
|
|
29
|
+
# Instale as dependências
|
|
30
|
+
npm install
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Configuração
|
|
34
|
+
|
|
35
|
+
1. Copie o arquivo de exemplo:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
cp .env.example .env
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
2. Configure suas credenciais em `.env`:
|
|
42
|
+
|
|
43
|
+
```env
|
|
44
|
+
GOOGLE_GEMINI_API_KEY=sua-chave-aqui
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Uso Básico
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
const { AutonomousCustomerServiceAgent, Type } = require('./src/index');
|
|
51
|
+
|
|
52
|
+
const agent = new AutonomousCustomerServiceAgent({
|
|
53
|
+
apiKey: process.env.GOOGLE_GEMINI_API_KEY,
|
|
54
|
+
company: {
|
|
55
|
+
name: 'Sua Empresa',
|
|
56
|
+
details: 'Descrição da empresa'
|
|
57
|
+
},
|
|
58
|
+
agent: {
|
|
59
|
+
name: 'Assistente',
|
|
60
|
+
mission: {
|
|
61
|
+
objective: 'Atuar como agente de atendimento e vendas',
|
|
62
|
+
instructions: 'Siga as diretrizes de qualificação e conversão.'
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
// Exemplo: modo de tratamento de falhas ("sync" ou "async")
|
|
66
|
+
failureHandlingMode: 'async',
|
|
67
|
+
retryScheduleMinutes: 5,
|
|
68
|
+
retryScheduleAttempts: 24,
|
|
69
|
+
// Mensagem enviada ao lead em caso de indisponibilidade temporária (modo async)
|
|
70
|
+
unavailabilityMessage: 'Estamos com uma indisponibilidade temporária. Entraremos em contato assim que o problema for sanado.'
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Registrar ferramentas customizadas
|
|
74
|
+
agent.registerTool({
|
|
75
|
+
name: 'get_product_info',
|
|
76
|
+
description: 'Obtém informações de produtos',
|
|
77
|
+
parameters: { type: Type.OBJECT, properties: {} }
|
|
78
|
+
}, async () => {
|
|
79
|
+
return JSON.stringify({ products: [] });
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Criar sessão
|
|
83
|
+
const sessionId = agent.createSession({
|
|
84
|
+
name: 'João Silva',
|
|
85
|
+
phone: '+55 11 98765-4321',
|
|
86
|
+
origin: { type: 'whatsapp' }
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Processar mensagem
|
|
90
|
+
const response = await agent.processMessage('Olá!', sessionId);
|
|
91
|
+
console.log(response.response);
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Novos parâmetros relacionados a tratamento de indisponibilidade:
|
|
95
|
+
|
|
96
|
+
```javascript
|
|
97
|
+
failureHandlingMode: 'sync' | 'async', // 'sync' bloqueia outras solicitações até conclusão; 'async' agenda tentativas e continua atendendo
|
|
98
|
+
retryScheduleMinutes: 5, // minutos entre tentativas agendadas
|
|
99
|
+
retryScheduleAttempts: 24, // número máximo de tentativas agendadas
|
|
100
|
+
retryScheduleWindowMs: 24 * 60 * 60 * 1000, // janela total para tentativas (em ms)
|
|
101
|
+
unavailabilityMessage: string, // mensagem customizável enviada ao lead em modo async
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Executar Testes
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
npm test
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## 📋 Configuração Avançada
|
|
111
|
+
|
|
112
|
+
Todas as opções de configuração com seus padrões:
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
new AutonomousCustomerServiceAgent({
|
|
116
|
+
apiKey: string, // Obrigatório
|
|
117
|
+
customer: { name: string, details?: string },
|
|
118
|
+
agent: {
|
|
119
|
+
name: string,
|
|
120
|
+
system_prompt_identity: string,
|
|
121
|
+
system_prompt_mission: string,
|
|
122
|
+
system_prompt_mission_instructions?: string
|
|
123
|
+
},
|
|
124
|
+
model: 'gemma-4-26b-a4b-it', // Modelo Gemini
|
|
125
|
+
maxAgenticLoopTurns: 8, // Max turns do agentic loop
|
|
126
|
+
sessionTTL: 1800000, // 30 min
|
|
127
|
+
turnTimeoutMs: 90000, // Timeout por turno
|
|
128
|
+
maxVulnerabilityAttempts: 3, // Limite de tentativas suspeitas
|
|
129
|
+
temperature: 0.2, // Criatividade (0-1)
|
|
130
|
+
topP: 0.95, // Diversidade
|
|
131
|
+
thinkingLevel: 'MINIMAL', // Raciocínio interno
|
|
132
|
+
maxOutputTokens: 4096, // Tokens máximos
|
|
133
|
+
retryOptions: {
|
|
134
|
+
maxAttempts: 3,
|
|
135
|
+
baseDelayMs: 500,
|
|
136
|
+
maxDelayMs: 8000
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## 🎯 Eventos
|
|
142
|
+
|
|
143
|
+
```javascript
|
|
144
|
+
agent.on('response', ({ response, sessionId }) => {});
|
|
145
|
+
agent.on('tool_call', ({ name, args }) => {});
|
|
146
|
+
agent.on('tool_result', ({ name, result }) => {});
|
|
147
|
+
agent.on('error', ({ error, source }) => {});
|
|
148
|
+
agent.on('session_created', ({ sessionId }) => {});
|
|
149
|
+
agent.on('session_expired', ({ sessionId }) => {});
|
|
150
|
+
agent.on('vulnerability_detected', ({ sessionId, reason }) => {});
|
|
151
|
+
agent.on('retry', ({ attempt, delay, error, sessionId }) => {});
|
|
152
|
+
// Eventos adicionados para os modos async/sync
|
|
153
|
+
agent.on('async_retry_scheduled', ({ sessionId, delay, attempts }) => {});
|
|
154
|
+
agent.on('async_retry_completed', ({ sessionId, attempts, result }) => {});
|
|
155
|
+
agent.on('sync_retry_started', ({ sessionId, attempt }) => {});
|
|
156
|
+
agent.on('sync_retry_completed', ({ sessionId, attempt, result }) => {});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## 🛠️ API
|
|
160
|
+
|
|
161
|
+
### Métodos Principais
|
|
162
|
+
|
|
163
|
+
- `createSession(lead)` - Cria nova sessão
|
|
164
|
+
- `processMessage(message, sessionId)` - Processa mensagem do cliente
|
|
165
|
+
- `registerTool(declaration, handler)` - Registra ferramenta customizada
|
|
166
|
+
- `clearSession(sessionId)` - Remove sessão
|
|
167
|
+
- `getSessionStatus(sessionId)` - Status da sessão
|
|
168
|
+
|
|
169
|
+
## 📝 Estrutura do Projeto
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
AutonomousCustomerServiceAgent/
|
|
173
|
+
├── src/
|
|
174
|
+
│ └── index.js # Agente principal
|
|
175
|
+
├── tests/
|
|
176
|
+
│ └── test.js # Exemplo de uso
|
|
177
|
+
├── .env.example # Template de variáveis
|
|
178
|
+
├── .gitignore # Arquivos ignorados
|
|
179
|
+
├── package.json # Dependências
|
|
180
|
+
└── README.md # Este arquivo
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## 🔐 Segurança
|
|
184
|
+
|
|
185
|
+
⚠️ **Nunca** commite o arquivo `.env` com credenciais reais no repositório!
|
|
186
|
+
|
|
187
|
+
O arquivo `.gitignore` já está configurado para ignorar:
|
|
188
|
+
- `.env` (credenciais)
|
|
189
|
+
- `node_modules/` (dependências)
|
|
190
|
+
- Logs e arquivos temporários
|
|
191
|
+
|
|
192
|
+
## 📄 Licença
|
|
193
|
+
|
|
194
|
+
ISC
|
|
195
|
+
|
|
196
|
+
## 👤 Autor
|
|
197
|
+
|
|
198
|
+
Áreum Tecnologia
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@areumtecnologia/autonomouscustomerserviceagent",
|
|
3
|
+
"version": "2.0.1",
|
|
4
|
+
"description": "Agente autônomo de atendimento ao cliente baseado em IA com Google Gemini API. Suporta múltiplas sessões, ferramentas customizadas e retry com backoff exponencial.",
|
|
5
|
+
"license": "ISC",
|
|
6
|
+
"author": "Áreum Tecnologia",
|
|
7
|
+
"type": "commonjs",
|
|
8
|
+
"main": "src/index.js",
|
|
9
|
+
"directories": {
|
|
10
|
+
"test": "tests"
|
|
11
|
+
},
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=16.0.0"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"ai",
|
|
17
|
+
"customer-service",
|
|
18
|
+
"chatbot",
|
|
19
|
+
"google-gemini",
|
|
20
|
+
"agent",
|
|
21
|
+
"agentic-loop",
|
|
22
|
+
"autonomous"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"test": "node tests/test.js",
|
|
26
|
+
"start": "node tests/test.js"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@areumtecnologia/autonomouscustomerserviceagent": "github:areumtecnologia/AutonomousCustomerServiceAgent",
|
|
30
|
+
"@google/genai": "^2.6.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"dotenv": "^17.4.2"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
|
|
2
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
3
|
+
// AgentConfig — construtor de configuração para o agente, usado internamente para complementar o prompt de sistema
|
|
4
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
5
|
+
class AgentConfig {
|
|
6
|
+
constructor(agentName, agentCompanyName, agentCompanyDetails, missionObjective, missionInstructions, reasoningLanguage = 'en_us') {
|
|
7
|
+
this.agentName = agentName;
|
|
8
|
+
this.agentCompanyName = agentCompanyName;
|
|
9
|
+
this.agentCompanyDetails = agentCompanyDetails;
|
|
10
|
+
this.missionObjective = missionObjective;
|
|
11
|
+
this.missionInstructions = missionInstructions;
|
|
12
|
+
this.reasoningLanguage = reasoningLanguage;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
build() {
|
|
16
|
+
return {
|
|
17
|
+
name: this.agentName,
|
|
18
|
+
company: {
|
|
19
|
+
name: this.agentCompanyName,
|
|
20
|
+
details: this.agentCompanyDetails
|
|
21
|
+
},
|
|
22
|
+
mission: {
|
|
23
|
+
objective: this.missionObjective,
|
|
24
|
+
instructions: this.missionInstructions
|
|
25
|
+
},
|
|
26
|
+
reasoningLanguage: this.reasoningLanguage
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = { AgentConfig };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// AgentEvents — fonte única de verdade para nomes de eventos
|
|
3
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
const AgentEvents = Object.freeze({
|
|
6
|
+
RESPONSE: 'response', // Resposta final estruturada
|
|
7
|
+
RAW_RESPONSE: 'raw_response', // Resposta bruta do modelo (candidatos)
|
|
8
|
+
TOOL_CALL: 'tool_call', // Antes de executar uma tool
|
|
9
|
+
TOOL_RESULT: 'tool_result', // Após a tool resolver
|
|
10
|
+
VULNERABILITY_EXPLORATION_DETECTED: 'vulnerability_exploration_detected', // Tentativa de exploração detectada
|
|
11
|
+
ERROR: 'error', // Erro irrecuperável
|
|
12
|
+
TURN_START: 'turn_start', // Início de um turno do loop
|
|
13
|
+
TURN_END: 'turn_end', // Fim de um turno do loop
|
|
14
|
+
SESSION_CREATED: 'session_created', // Nova sessão criada
|
|
15
|
+
SESSION_EXPIRED: 'session_expired', // Sessão expirou por TTL
|
|
16
|
+
SESSION_CLEARED: 'session_cleared', // Sessão removida manualmente
|
|
17
|
+
RETRY: 'retry', // Retry após falha na API
|
|
18
|
+
ASYNC_RETRY_SCHEDULED: 'async_retry_scheduled', // Retry assíncrono agendado
|
|
19
|
+
ASYNC_RETRY_COMPLETED: 'async_retry_completed', // Retry assíncrono concluído
|
|
20
|
+
SYNC_RETRY_STARTED: 'sync_retry_started', // Retry síncrono iniciado
|
|
21
|
+
SYNC_RETRY_COMPLETED: 'sync_retry_completed', // Retry síncrono concluído
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
module.exports = { AgentEvents };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Uma classe para armazenar e gerenciar agentes
|
|
2
|
+
class AgentManager {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.agents = new Map();
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
add(id, agent) {
|
|
8
|
+
if (!(agent instanceof AutonomousCustomerServiceAgent)) {
|
|
9
|
+
throw new TypeError('Only instances of AutonomousCustomerServiceAgent can be added.');
|
|
10
|
+
}
|
|
11
|
+
this.agents.set(id, agent);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
get(id) {
|
|
15
|
+
return this.agents.get(id);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
remove(id) {
|
|
19
|
+
return this.agents.delete(id);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
list() {
|
|
23
|
+
return Array.from(this.agents.keys());
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
clear() {
|
|
27
|
+
this.agents.clear();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = { AgentManager };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
|
|
2
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
3
|
+
// AgentSession — encapsula todo o estado de uma conversa
|
|
4
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
5
|
+
|
|
6
|
+
class AgentSession {
|
|
7
|
+
/** @type {string} */ id;
|
|
8
|
+
/** @type {object} */ user;
|
|
9
|
+
/** @type {object[]} */ history = []; // `contents` acumulado (todos os turns)
|
|
10
|
+
/** @type {number} */ vulnerabilityCount = 0;
|
|
11
|
+
/** @type {boolean} */ terminated = false;
|
|
12
|
+
/** @type {Date} */ createdAt = new Date();
|
|
13
|
+
/** @type {Date} */ lastActivity = new Date();
|
|
14
|
+
/** @type {object|null} */ retryState = null;
|
|
15
|
+
|
|
16
|
+
#ttlTimer = null;
|
|
17
|
+
#onExpire;
|
|
18
|
+
|
|
19
|
+
constructor(id, user, onExpire) {
|
|
20
|
+
this.id = id;
|
|
21
|
+
this.user = Object.freeze({ ...user });
|
|
22
|
+
this.#onExpire = onExpire;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
touch() { this.lastActivity = new Date(); }
|
|
26
|
+
|
|
27
|
+
scheduleTTL(ms) {
|
|
28
|
+
this.cancelTTL();
|
|
29
|
+
this.#ttlTimer = setTimeout(() => this.#onExpire(this.id), ms);
|
|
30
|
+
this.#ttlTimer.unref?.(); // não bloqueia shutdown do processo
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
cancelTTL() {
|
|
34
|
+
if (this.#ttlTimer) { clearTimeout(this.#ttlTimer); this.#ttlTimer = null; }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
appendHistory(...turns) { this.history.push(...turns); }
|
|
38
|
+
|
|
39
|
+
toJSON() {
|
|
40
|
+
return {
|
|
41
|
+
id: this.id,
|
|
42
|
+
user: this.user,
|
|
43
|
+
vulnerabilityCount: this.vulnerabilityCount,
|
|
44
|
+
terminated: this.terminated,
|
|
45
|
+
createdAt: this.createdAt,
|
|
46
|
+
lastActivity: this.lastActivity,
|
|
47
|
+
turns: this.history.length,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = { AgentSession };
|