atendentepro 0.5.9__py3-none-any.whl → 0.6.1__py3-none-any.whl

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.
atendentepro/README.md CHANGED
@@ -1191,7 +1191,81 @@ flowchart LR
1191
1191
  FEED --> |Protocolo TKT| EMAIL[Email + Ticket]
1192
1192
  ```
1193
1193
 
1194
- ### Passo 11: Criar Rede Específica (Opcional)
1194
+ ### Passo 11: Configurar Estilo de Comunicação (Opcional - style_config.yaml)
1195
+
1196
+ O **AgentStyle** permite personalizar o tom e estilo de comunicação dos agentes.
1197
+
1198
+ #### Configuração YAML
1199
+
1200
+ ```yaml
1201
+ # style_config.yaml
1202
+
1203
+ # Estilo Global (aplicado a todos os agentes por padrão)
1204
+ global:
1205
+ tone: "profissional e cordial"
1206
+ language_style: "formal" # formal, informal, neutro
1207
+ response_length: "moderado" # conciso, moderado, detalhado
1208
+ custom_rules: |
1209
+ - Seja objetivo e claro nas respostas
1210
+ - Use linguagem inclusiva
1211
+
1212
+ # Estilos específicos por agente (sobrescrevem o global)
1213
+ agents:
1214
+ escalation:
1215
+ tone: "empático e tranquilizador"
1216
+ custom_rules: |
1217
+ - Demonstre compreensão pela situação do usuário
1218
+ - Assegure que o problema será resolvido
1219
+
1220
+ knowledge:
1221
+ tone: "didático e paciente"
1222
+ response_length: "detalhado"
1223
+ custom_rules: |
1224
+ - Explique conceitos de forma acessível
1225
+ - Cite as fontes das informações
1226
+ ```
1227
+
1228
+ #### Uso Programático com AgentStyle
1229
+
1230
+ ```python
1231
+ from pathlib import Path
1232
+ from atendentepro import create_standard_network, AgentStyle
1233
+
1234
+ # Estilo global formal
1235
+ global_style = AgentStyle(
1236
+ tone="profissional e consultivo",
1237
+ language_style="formal",
1238
+ response_length="moderado",
1239
+ custom_rules="Sempre se apresente como assistente da empresa.",
1240
+ )
1241
+
1242
+ # Estilo específico para escalation (mais empático)
1243
+ escalation_style = AgentStyle(
1244
+ tone="empático e acolhedor",
1245
+ custom_rules="Demonstre compreensão e assegure resolução.",
1246
+ )
1247
+
1248
+ network = create_standard_network(
1249
+ templates_root=Path("./client_templates"),
1250
+ client="meu_cliente",
1251
+ global_style=global_style,
1252
+ agent_styles={
1253
+ "escalation": escalation_style,
1254
+ "feedback": AgentStyle(tone="solícito", custom_rules="Agradeça o feedback."),
1255
+ },
1256
+ )
1257
+ ```
1258
+
1259
+ #### Opções Disponíveis
1260
+
1261
+ | Parâmetro | Valores | Descrição |
1262
+ |-----------|---------|-----------|
1263
+ | `tone` | Texto livre | Tom da conversa (ex: "profissional", "empático") |
1264
+ | `language_style` | `formal`, `informal`, `neutro` | Nível de formalidade |
1265
+ | `response_length` | `conciso`, `moderado`, `detalhado` | Tamanho das respostas |
1266
+ | `custom_rules` | Texto livre | Regras adicionais personalizadas |
1267
+
1268
+ ### Passo 12: Criar Rede Específica (Opcional)
1195
1269
 
1196
1270
  Se precisar de lógica customizada:
1197
1271
 
@@ -1285,6 +1359,7 @@ client_templates/meu_cliente/
1285
1359
  ├── escalation_config.yaml # ✅ Recomendado - Transferência humana
1286
1360
  ├── feedback_config.yaml # ✅ Recomendado - Tickets/SAC
1287
1361
  ├── guardrails_config.yaml # ✅ Recomendado - Políticas de segurança
1362
+ ├── style_config.yaml # Opcional - Tom e estilo de comunicação
1288
1363
 
1289
1364
  │ # Dados (opcionais)
1290
1365
  ├── data/ # Dados estruturados
@@ -1310,6 +1385,7 @@ client_templates/meu_cliente/
1310
1385
  | `escalation_config.yaml` | Escalation | Recomendado | Canais e triggers |
1311
1386
  | `feedback_config.yaml` | Feedback | Recomendado | Tipos ticket e email |
1312
1387
  | `guardrails_config.yaml` | Todos | Recomendado | Escopo e restrições |
1388
+ | `style_config.yaml` | Todos | Opcional | Tom e estilo de comunicação |
1313
1389
 
1314
1390
  ---
1315
1391
 
atendentepro/__init__.py CHANGED
@@ -113,6 +113,7 @@ from atendentepro.agents import (
113
113
  # Network
114
114
  from atendentepro.network import (
115
115
  AgentNetwork,
116
+ AgentStyle,
116
117
  create_standard_network,
117
118
  create_custom_network,
118
119
  )
@@ -211,6 +212,7 @@ __all__ = [
211
212
  "configure_feedback_storage",
212
213
  # Network
213
214
  "AgentNetwork",
215
+ "AgentStyle",
214
216
  "create_standard_network",
215
217
  "create_custom_network",
216
218
  # Templates
@@ -25,6 +25,7 @@ def create_answer_agent(
25
25
  guardrails: Optional[List["GuardrailCallable"]] = None,
26
26
  name: str = "Answer Agent",
27
27
  custom_instructions: Optional[str] = None,
28
+ style_instructions: str = "",
28
29
  ) -> AnswerAgent:
29
30
  """
30
31
  Create an Answer Agent instance.
@@ -38,6 +39,7 @@ def create_answer_agent(
38
39
  guardrails: List of input guardrails.
39
40
  name: Agent name.
40
41
  custom_instructions: Optional custom instructions to override default.
42
+ style_instructions: Optional style/tone instructions to append.
41
43
 
42
44
  Returns:
43
45
  Configured Answer Agent instance.
@@ -48,6 +50,10 @@ def create_answer_agent(
48
50
  prompt = get_answer_prompt(answer_template=answer_template)
49
51
  instructions = f"{RECOMMENDED_PROMPT_PREFIX} {prompt}"
50
52
 
53
+ # Append style instructions if provided
54
+ if style_instructions:
55
+ instructions += style_instructions
56
+
51
57
  return Agent[ContextNote](
52
58
  name=name,
53
59
  handoff_description=(
@@ -27,6 +27,7 @@ def create_confirmation_agent(
27
27
  guardrails: Optional[List["GuardrailCallable"]] = None,
28
28
  name: str = "Confirmation Agent",
29
29
  custom_instructions: Optional[str] = None,
30
+ style_instructions: str = "",
30
31
  ) -> ConfirmationAgent:
31
32
  """
32
33
  Create a Confirmation Agent instance.
@@ -42,6 +43,7 @@ def create_confirmation_agent(
42
43
  guardrails: List of input guardrails.
43
44
  name: Agent name.
44
45
  custom_instructions: Optional custom instructions to override default.
46
+ style_instructions: Optional style/tone instructions to append.
45
47
 
46
48
  Returns:
47
49
  Configured Confirmation Agent instance.
@@ -56,6 +58,10 @@ def create_confirmation_agent(
56
58
  )
57
59
  instructions = f"{RECOMMENDED_PROMPT_PREFIX} {prompt}"
58
60
 
61
+ # Append style instructions if provided
62
+ if style_instructions:
63
+ instructions += style_instructions
64
+
59
65
  return Agent[ContextNote](
60
66
  name=name,
61
67
  handoff_description=(
@@ -454,6 +454,7 @@ def create_escalation_agent(
454
454
  guardrails: Optional[List["GuardrailCallable"]] = None,
455
455
  name: str = "Escalation Agent",
456
456
  custom_instructions: Optional[str] = None,
457
+ style_instructions: str = "",
457
458
  ) -> EscalationAgent:
458
459
  """
459
460
  Create an Escalation Agent instance.
@@ -475,6 +476,7 @@ def create_escalation_agent(
475
476
  guardrails: List of input guardrails.
476
477
  name: Agent name.
477
478
  custom_instructions: Optional custom instructions to override default.
479
+ style_instructions: Optional style/tone instructions to append.
478
480
 
479
481
  Returns:
480
482
  Configured Escalation Agent instance.
@@ -494,6 +496,10 @@ def create_escalation_agent(
494
496
  # Usar o prompt builder do módulo prompts
495
497
  instructions = f"{RECOMMENDED_PROMPT_PREFIX}\n{get_escalation_prompt(escalation_triggers=escalation_triggers, escalation_channels=escalation_channels)}"
496
498
 
499
+ # Append style instructions if provided
500
+ if style_instructions:
501
+ instructions += style_instructions
502
+
497
503
  # Combinar tools padrão com customizadas
498
504
  agent_tools = list(ESCALATION_TOOLS)
499
505
  if tools:
@@ -894,6 +894,7 @@ def create_feedback_agent(
894
894
  guardrails: Optional[List["GuardrailCallable"]] = None,
895
895
  name: str = "Feedback Agent",
896
896
  custom_instructions: Optional[str] = None,
897
+ style_instructions: str = "",
897
898
  ) -> FeedbackAgent:
898
899
  """
899
900
  Create a Feedback Agent for collecting user feedback, questions, and complaints.
@@ -919,6 +920,7 @@ def create_feedback_agent(
919
920
  guardrails: List of input guardrails.
920
921
  name: Agent name.
921
922
  custom_instructions: Override default instructions.
923
+ style_instructions: Optional style/tone instructions to append.
922
924
 
923
925
  Returns:
924
926
  Configured Feedback Agent instance.
@@ -945,6 +947,10 @@ def create_feedback_agent(
945
947
  # Usar o prompt builder do módulo prompts
946
948
  instructions = f"{RECOMMENDED_PROMPT_PREFIX}\n{get_feedback_prompt(ticket_types=ticket_types, protocol_prefix=protocol_prefix, brand_name=email_brand_name, sla_message=email_sla_message)}"
947
949
 
950
+ # Append style instructions if provided
951
+ if style_instructions:
952
+ instructions += style_instructions
953
+
948
954
  # Combine tools
949
955
  agent_tools = list(FEEDBACK_TOOLS)
950
956
  if tools:
@@ -26,6 +26,7 @@ def create_flow_agent(
26
26
  guardrails: Optional[List["GuardrailCallable"]] = None,
27
27
  name: str = "Flow Agent",
28
28
  custom_instructions: Optional[str] = None,
29
+ style_instructions: str = "",
29
30
  ) -> FlowAgent:
30
31
  """
31
32
  Create a Flow Agent instance.
@@ -39,6 +40,7 @@ def create_flow_agent(
39
40
  guardrails: List of input guardrails.
40
41
  name: Agent name.
41
42
  custom_instructions: Optional custom instructions to override default.
43
+ style_instructions: Optional style/tone instructions to append.
42
44
 
43
45
  Returns:
44
46
  Configured Flow Agent instance.
@@ -49,6 +51,10 @@ def create_flow_agent(
49
51
  prompt = get_flow_prompt(flow_template=flow_template, flow_keywords=flow_keywords)
50
52
  instructions = f"{RECOMMENDED_PROMPT_PREFIX} {prompt}"
51
53
 
54
+ # Append style instructions if provided
55
+ if style_instructions:
56
+ instructions += style_instructions
57
+
52
58
  return Agent[ContextNote](
53
59
  name=name,
54
60
  handoff_description="""
@@ -27,6 +27,7 @@ def create_interview_agent(
27
27
  guardrails: Optional[List["GuardrailCallable"]] = None,
28
28
  name: str = "Interview Agent",
29
29
  custom_instructions: Optional[str] = None,
30
+ style_instructions: str = "",
30
31
  ) -> InterviewAgent:
31
32
  """
32
33
  Create an Interview Agent instance.
@@ -42,6 +43,7 @@ def create_interview_agent(
42
43
  guardrails: List of input guardrails.
43
44
  name: Agent name.
44
45
  custom_instructions: Optional custom instructions to override default.
46
+ style_instructions: Optional style/tone instructions to append.
45
47
 
46
48
  Returns:
47
49
  Configured Interview Agent instance.
@@ -55,6 +57,10 @@ def create_interview_agent(
55
57
  )
56
58
  instructions = f"{RECOMMENDED_PROMPT_PREFIX} {prompt}"
57
59
 
60
+ # Append style instructions if provided
61
+ if style_instructions:
62
+ instructions += style_instructions
63
+
58
64
  return Agent[ContextNote](
59
65
  name=name,
60
66
  handoff_description="""
@@ -217,6 +217,7 @@ def create_knowledge_agent(
217
217
  guardrails: Optional[List["GuardrailCallable"]] = None,
218
218
  name: str = "Knowledge Agent",
219
219
  custom_instructions: Optional[str] = None,
220
+ style_instructions: str = "",
220
221
  ) -> KnowledgeAgent:
221
222
  """
222
223
  Create a Knowledge Agent instance.
@@ -239,6 +240,7 @@ def create_knowledge_agent(
239
240
  guardrails: List of input guardrails.
240
241
  name: Agent name.
241
242
  custom_instructions: Optional custom instructions to override default.
243
+ style_instructions: Optional style/tone instructions to append.
242
244
 
243
245
  Returns:
244
246
  Configured Knowledge Agent instance.
@@ -262,6 +264,10 @@ def create_knowledge_agent(
262
264
  )
263
265
  instructions = f"{RECOMMENDED_PROMPT_PREFIX} {prompt}"
264
266
 
267
+ # Append style instructions if provided
268
+ if style_instructions:
269
+ instructions += style_instructions
270
+
265
271
  # Build tools list
266
272
  agent_tools: List = []
267
273
 
@@ -27,6 +27,7 @@ def create_onboarding_agent(
27
27
  guardrails: Optional[List["GuardrailCallable"]] = None,
28
28
  name: str = "Onboarding Agent",
29
29
  custom_instructions: Optional[str] = None,
30
+ style_instructions: str = "",
30
31
  ) -> OnboardingAgent:
31
32
  """
32
33
  Create an Onboarding Agent instance.
@@ -41,6 +42,7 @@ def create_onboarding_agent(
41
42
  guardrails: List of input guardrails.
42
43
  name: Agent name.
43
44
  custom_instructions: Optional custom instructions to override default.
45
+ style_instructions: Optional style/tone instructions to append.
44
46
 
45
47
  Returns:
46
48
  Configured Onboarding Agent instance.
@@ -51,6 +53,10 @@ def create_onboarding_agent(
51
53
  prompt = get_onboarding_prompt(required_fields=required_fields)
52
54
  instructions = f"{RECOMMENDED_PROMPT_PREFIX} {prompt}"
53
55
 
56
+ # Append style instructions if provided
57
+ if style_instructions:
58
+ instructions += style_instructions
59
+
54
60
  return Agent[ContextNote](
55
61
  name=name,
56
62
  handoff_description=(
@@ -25,6 +25,7 @@ def create_triage_agent(
25
25
  guardrails: Optional[List["GuardrailCallable"]] = None,
26
26
  name: str = "Triage Agent",
27
27
  custom_instructions: Optional[str] = None,
28
+ style_instructions: str = "",
28
29
  ) -> TriageAgent:
29
30
  """
30
31
  Create a Triage Agent instance.
@@ -38,6 +39,7 @@ def create_triage_agent(
38
39
  guardrails: List of input guardrails.
39
40
  name: Agent name.
40
41
  custom_instructions: Optional custom instructions to override default.
42
+ style_instructions: Optional style/tone instructions to append.
41
43
 
42
44
  Returns:
43
45
  Configured Triage Agent instance.
@@ -47,6 +49,10 @@ def create_triage_agent(
47
49
  else:
48
50
  instructions = f"{RECOMMENDED_PROMPT_PREFIX} {get_triage_prompt(keywords_text)}"
49
51
 
52
+ # Append style instructions if provided
53
+ if style_instructions:
54
+ instructions += style_instructions
55
+
50
56
  return Agent[ContextNote](
51
57
  name=name,
52
58
  handoff_description="A triage agent that can delegate a customer's request to the appropriate agent.",
@@ -29,6 +29,7 @@ def create_usage_agent(
29
29
  guardrails: Optional[List["GuardrailCallable"]] = None,
30
30
  name: str = "Usage Agent",
31
31
  custom_instructions: Optional[str] = None,
32
+ style_instructions: str = "",
32
33
  ) -> UsageAgent:
33
34
  """
34
35
  Create a Usage Agent instance.
@@ -40,12 +41,17 @@ def create_usage_agent(
40
41
  guardrails: List of input guardrails.
41
42
  name: Agent name.
42
43
  custom_instructions: Optional custom instructions to override default.
44
+ style_instructions: Optional style/tone instructions to append.
43
45
 
44
46
  Returns:
45
47
  Configured Usage Agent instance.
46
48
  """
47
49
  instructions = custom_instructions or DEFAULT_USAGE_INSTRUCTIONS
48
50
 
51
+ # Append style instructions if provided
52
+ if style_instructions:
53
+ instructions += style_instructions
54
+
49
55
  return Agent[ContextNote](
50
56
  name=name,
51
57
  handoff_description="A usage agent that can answer questions about the usage of the system.",
atendentepro/network.py CHANGED
@@ -11,6 +11,84 @@ from dataclasses import dataclass, field
11
11
  from pathlib import Path
12
12
  from typing import Any, Callable, Dict, List, Literal, Optional
13
13
 
14
+
15
+ # =============================================================================
16
+ # Agent Style Configuration
17
+ # =============================================================================
18
+
19
+ @dataclass
20
+ class AgentStyle:
21
+ """
22
+ Configuration for agent conversation style and tone.
23
+
24
+ Allows customizing how agents communicate with users,
25
+ including tone, language style, response length, and custom rules.
26
+
27
+ Attributes:
28
+ tone: Conversation tone (e.g., "profissional", "empático", "consultivo")
29
+ language_style: Language formality ("formal", "informal", "neutro")
30
+ response_length: Response verbosity ("conciso", "moderado", "detalhado")
31
+ custom_rules: Additional custom rules as text
32
+
33
+ Example:
34
+ >>> style = AgentStyle(
35
+ ... tone="empático e acolhedor",
36
+ ... language_style="formal",
37
+ ... response_length="moderado",
38
+ ... custom_rules="Sempre se apresente como assistente da empresa."
39
+ ... )
40
+ >>> print(style.build_style_prompt())
41
+ """
42
+
43
+ tone: str = ""
44
+ language_style: str = "" # formal, informal, neutro
45
+ response_length: str = "" # conciso, moderado, detalhado
46
+ custom_rules: str = ""
47
+
48
+ def build_style_prompt(self) -> str:
49
+ """
50
+ Build style instructions to append to agent prompts.
51
+
52
+ Returns:
53
+ Formatted style instructions as a string.
54
+ """
55
+ parts = []
56
+
57
+ if self.tone:
58
+ parts.append(f"**Tom de conversa:** {self.tone}.")
59
+
60
+ if self.language_style:
61
+ style_map = {
62
+ "formal": "Use linguagem formal e respeitosa, evitando gírias e expressões coloquiais.",
63
+ "informal": "Use linguagem informal e descontraída, aproximando-se do usuário.",
64
+ "neutro": "Use linguagem neutra e objetiva, focando na clareza.",
65
+ }
66
+ instruction = style_map.get(
67
+ self.language_style.lower(),
68
+ f"Estilo de linguagem: {self.language_style}"
69
+ )
70
+ parts.append(f"**Linguagem:** {instruction}")
71
+
72
+ if self.response_length:
73
+ length_map = {
74
+ "conciso": "Seja conciso e direto nas respostas, evitando informações desnecessárias.",
75
+ "moderado": "Forneça respostas com nível médio de detalhe, equilibrando clareza e completude.",
76
+ "detalhado": "Forneça respostas detalhadas e completas, explicando cada ponto relevante.",
77
+ }
78
+ instruction = length_map.get(
79
+ self.response_length.lower(),
80
+ f"Tamanho das respostas: {self.response_length}"
81
+ )
82
+ parts.append(f"**Respostas:** {instruction}")
83
+
84
+ if self.custom_rules:
85
+ parts.append(f"**Regras adicionais:**\n{self.custom_rules}")
86
+
87
+ if not parts:
88
+ return ""
89
+
90
+ return "\n\n## Estilo de Comunicação\n" + "\n\n".join(parts)
91
+
14
92
  from atendentepro.agents import (
15
93
  create_triage_agent,
16
94
  create_flow_agent,
@@ -118,6 +196,9 @@ def create_standard_network(
118
196
  feedback_brand_color: str = "#4A90D9",
119
197
  feedback_brand_name: str = "Atendimento",
120
198
  custom_tools: Optional[Dict[str, List]] = None,
199
+ # Style configuration
200
+ global_style: Optional[AgentStyle] = None,
201
+ agent_styles: Optional[Dict[str, AgentStyle]] = None,
121
202
  ) -> AgentNetwork:
122
203
  """
123
204
  Create a standard agent network with proper handoff configuration.
@@ -153,6 +234,8 @@ def create_standard_network(
153
234
  feedback_brand_color: Brand color for feedback emails.
154
235
  feedback_brand_name: Brand name for feedback emails.
155
236
  custom_tools: Optional dict of custom tools by agent name.
237
+ global_style: Style configuration applied to all agents (tone, language, etc.).
238
+ agent_styles: Dict mapping agent names to specific styles (overrides global).
156
239
 
157
240
  Returns:
158
241
  Configured AgentNetwork instance.
@@ -178,6 +261,23 @@ def create_standard_network(
178
261
  include_escalation=False,
179
262
  include_feedback=False,
180
263
  )
264
+
265
+ # Create network with custom communication style
266
+ network = create_standard_network(
267
+ templates_root=Path("templates"),
268
+ client="my_client",
269
+ global_style=AgentStyle(
270
+ tone="profissional e consultivo",
271
+ language_style="formal",
272
+ response_length="moderado",
273
+ ),
274
+ agent_styles={
275
+ "escalation": AgentStyle(
276
+ tone="empático e acolhedor",
277
+ custom_rules="Demonstre compreensão pela situação.",
278
+ ),
279
+ },
280
+ )
181
281
  """
182
282
  # Verificar licença
183
283
  require_activation()
@@ -245,11 +345,23 @@ def create_standard_network(
245
345
  # Get custom tools
246
346
  tools = custom_tools or {}
247
347
 
348
+ # Style helper function
349
+ def get_style_for_agent(agent_name: str) -> str:
350
+ """Get style instructions for a specific agent."""
351
+ # Agent-specific style takes precedence
352
+ if agent_styles and agent_name in agent_styles:
353
+ return agent_styles[agent_name].build_style_prompt()
354
+ # Fall back to global style
355
+ if global_style:
356
+ return global_style.build_style_prompt()
357
+ return ""
358
+
248
359
  # Create agents without handoffs first
249
360
  # Triage is always created (entry point)
250
361
  triage = create_triage_agent(
251
362
  keywords_text=triage_keywords,
252
363
  guardrails=get_guardrails_for_agent("Triage Agent", templates_root),
364
+ style_instructions=get_style_for_agent("triage"),
253
365
  )
254
366
 
255
367
  # Create optional agents based on include flags
@@ -259,6 +371,7 @@ def create_standard_network(
259
371
  flow_template=flow_template,
260
372
  flow_keywords=flow_keywords,
261
373
  guardrails=get_guardrails_for_agent("Flow Agent", templates_root),
374
+ style_instructions=get_style_for_agent("flow"),
262
375
  )
263
376
 
264
377
  interview = None
@@ -268,6 +381,7 @@ def create_standard_network(
268
381
  interview_questions=interview_questions,
269
382
  tools=tools.get("interview", []),
270
383
  guardrails=get_guardrails_for_agent("Interview Agent", templates_root),
384
+ style_instructions=get_style_for_agent("interview"),
271
385
  )
272
386
 
273
387
  answer = None
@@ -275,6 +389,7 @@ def create_standard_network(
275
389
  answer = create_answer_agent(
276
390
  answer_template="",
277
391
  guardrails=get_guardrails_for_agent("Answer Agent", templates_root),
392
+ style_instructions=get_style_for_agent("answer"),
278
393
  )
279
394
 
280
395
  knowledge = None
@@ -288,6 +403,7 @@ def create_standard_network(
288
403
  include_rag_tool=has_embeddings,
289
404
  tools=tools.get("knowledge", []),
290
405
  guardrails=get_guardrails_for_agent("Knowledge Agent", templates_root),
406
+ style_instructions=get_style_for_agent("knowledge"),
291
407
  )
292
408
 
293
409
  confirmation = None
@@ -297,12 +413,14 @@ def create_standard_network(
297
413
  confirmation_template=confirmation_template,
298
414
  confirmation_format=confirmation_format,
299
415
  guardrails=get_guardrails_for_agent("Confirmation Agent", templates_root),
416
+ style_instructions=get_style_for_agent("confirmation"),
300
417
  )
301
418
 
302
419
  usage = None
303
420
  if include_usage:
304
421
  usage = create_usage_agent(
305
422
  guardrails=get_guardrails_for_agent("Usage Agent", templates_root),
423
+ style_instructions=get_style_for_agent("usage"),
306
424
  )
307
425
 
308
426
  # Create escalation agent if requested
@@ -312,6 +430,7 @@ def create_standard_network(
312
430
  escalation_channels=escalation_channels,
313
431
  tools=tools.get("escalation", []),
314
432
  guardrails=get_guardrails_for_agent("Escalation Agent", templates_root),
433
+ style_instructions=get_style_for_agent("escalation"),
315
434
  )
316
435
 
317
436
  # Create feedback agent if requested
@@ -323,6 +442,7 @@ def create_standard_network(
323
442
  email_brand_name=feedback_brand_name,
324
443
  tools=tools.get("feedback", []),
325
444
  guardrails=get_guardrails_for_agent("Feedback Agent", templates_root),
445
+ style_instructions=get_style_for_agent("feedback"),
326
446
  )
327
447
 
328
448
  # Configure handoffs dynamically based on which agents are included
@@ -433,6 +553,7 @@ def create_standard_network(
433
553
  required_fields=fields,
434
554
  tools=tools.get("onboarding", []),
435
555
  guardrails=get_guardrails_for_agent("Onboarding Agent", templates_root),
556
+ style_instructions=get_style_for_agent("onboarding"),
436
557
  )
437
558
 
438
559
  network.onboarding = onboarding
@@ -14,12 +14,15 @@ from .manager import (
14
14
  load_knowledge_config,
15
15
  load_confirmation_config,
16
16
  load_onboarding_config,
17
+ load_style_config,
17
18
  FlowConfig,
18
19
  InterviewConfig,
19
20
  TriageConfig,
20
21
  KnowledgeConfig,
21
22
  ConfirmationConfig,
22
23
  OnboardingConfig,
24
+ StyleConfig,
25
+ AgentStyleConfig,
23
26
  DataSourceConfig,
24
27
  DataSourceColumn,
25
28
  DocumentConfig,
@@ -38,12 +41,15 @@ __all__ = [
38
41
  "load_knowledge_config",
39
42
  "load_confirmation_config",
40
43
  "load_onboarding_config",
44
+ "load_style_config",
41
45
  "FlowConfig",
42
46
  "InterviewConfig",
43
47
  "TriageConfig",
44
48
  "KnowledgeConfig",
45
49
  "ConfirmationConfig",
46
50
  "OnboardingConfig",
51
+ "StyleConfig",
52
+ "AgentStyleConfig",
47
53
  "DataSourceConfig",
48
54
  "DataSourceColumn",
49
55
  "DocumentConfig",
@@ -314,6 +314,83 @@ class OnboardingField(BaseModel):
314
314
  priority: int = 0
315
315
 
316
316
 
317
+ class AgentStyleConfig(BaseModel):
318
+ """Configuration for individual agent style."""
319
+
320
+ tone: str = ""
321
+ language_style: str = "" # formal, informal, neutro
322
+ response_length: str = "" # conciso, moderado, detalhado
323
+ custom_rules: str = ""
324
+
325
+
326
+ class StyleConfig(BaseModel):
327
+ """Configuration model for agent communication styles.
328
+
329
+ Allows customizing tone, language, and response style globally
330
+ or per-agent through YAML configuration.
331
+
332
+ Example YAML:
333
+ global:
334
+ tone: "profissional e cordial"
335
+ language_style: "formal"
336
+ response_length: "moderado"
337
+
338
+ agents:
339
+ escalation:
340
+ tone: "empático e acolhedor"
341
+ custom_rules: "Demonstre compreensão"
342
+ """
343
+
344
+ global_style: AgentStyleConfig = Field(default_factory=AgentStyleConfig)
345
+ agents: Dict[str, AgentStyleConfig] = Field(default_factory=dict)
346
+
347
+ @classmethod
348
+ @lru_cache(maxsize=4)
349
+ def load(cls, path: Path) -> "StyleConfig":
350
+ """Load style configuration from YAML file."""
351
+ if not path.exists():
352
+ raise FileNotFoundError(f"Style config not found at {path}")
353
+
354
+ with open(path, "r", encoding="utf-8") as f:
355
+ data = yaml.safe_load(f) or {}
356
+
357
+ # Parse global style
358
+ global_data = data.get("global", {})
359
+ global_style = AgentStyleConfig(
360
+ tone=global_data.get("tone", ""),
361
+ language_style=global_data.get("language_style", ""),
362
+ response_length=global_data.get("response_length", ""),
363
+ custom_rules=global_data.get("custom_rules", ""),
364
+ )
365
+
366
+ # Parse agent-specific styles
367
+ agents = {}
368
+ for agent_name, agent_data in data.get("agents", {}).items():
369
+ agents[agent_name] = AgentStyleConfig(
370
+ tone=agent_data.get("tone", ""),
371
+ language_style=agent_data.get("language_style", ""),
372
+ response_length=agent_data.get("response_length", ""),
373
+ custom_rules=agent_data.get("custom_rules", ""),
374
+ )
375
+
376
+ return cls(global_style=global_style, agents=agents)
377
+
378
+ def get_style_for_agent(self, agent_name: str) -> AgentStyleConfig:
379
+ """Get style configuration for a specific agent."""
380
+ # Agent-specific style takes precedence
381
+ if agent_name in self.agents:
382
+ agent_style = self.agents[agent_name]
383
+ # Merge with global (agent-specific overrides global)
384
+ return AgentStyleConfig(
385
+ tone=agent_style.tone or self.global_style.tone,
386
+ language_style=agent_style.language_style or self.global_style.language_style,
387
+ response_length=agent_style.response_length or self.global_style.response_length,
388
+ custom_rules=agent_style.custom_rules or self.global_style.custom_rules,
389
+ )
390
+ # Fall back to global
391
+ return self.global_style
392
+
393
+
317
394
  class OnboardingConfig(BaseModel):
318
395
  """Configuration model for Onboarding Agent."""
319
396
 
@@ -432,6 +509,11 @@ class TemplateManager:
432
509
  folder = self.get_template_folder(client)
433
510
  return OnboardingConfig.load(folder / "onboarding_config.yaml")
434
511
 
512
+ def load_style_config(self, client: Optional[str] = None) -> StyleConfig:
513
+ """Load style configuration for the specified client."""
514
+ folder = self.get_template_folder(client)
515
+ return StyleConfig.load(folder / "style_config.yaml")
516
+
435
517
  def clear_caches(self) -> None:
436
518
  """Clear all configuration caches."""
437
519
  FlowConfig.load.cache_clear()
@@ -440,6 +522,7 @@ class TemplateManager:
440
522
  KnowledgeConfig.load.cache_clear()
441
523
  ConfirmationConfig.load.cache_clear()
442
524
  OnboardingConfig.load.cache_clear()
525
+ StyleConfig.load.cache_clear()
443
526
 
444
527
 
445
528
  def get_template_manager() -> TemplateManager:
@@ -528,3 +611,8 @@ def load_onboarding_config(client: Optional[str] = None) -> OnboardingConfig:
528
611
  """Load onboarding configuration for the specified client."""
529
612
  return get_template_manager().load_onboarding_config(client)
530
613
 
614
+
615
+ def load_style_config(client: Optional[str] = None) -> StyleConfig:
616
+ """Load style configuration for the specified client."""
617
+ return get_template_manager().load_style_config(client)
618
+
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: atendentepro
3
- Version: 0.5.9
4
- Summary: Framework de orquestração de agentes IA para resolver interações complexas integrando múltiplas fontes de dados (documentos, APIs, bancos) em uma única plataforma inteligente.
3
+ Version: 0.6.1
4
+ Summary: Framework de orquestração de agentes IA com tom e estilo customizáveis. Integra documentos (RAG), APIs e bancos de dados em uma plataforma inteligente multi-agente.
5
5
  Author-email: BeMonkAI <contato@monkai.com.br>
6
6
  Maintainer-email: BeMonkAI <contato@monkai.com.br>
7
7
  License: Proprietary
@@ -73,6 +73,7 @@ Plataforma que unifica múltiplos agentes especializados para resolver demandas
73
73
  | **Classificação Inteligente** | Identifica a intenção e direciona para o agente especializado |
74
74
  | **Integração de Dados** | Conecta documentos (RAG), CSVs, bancos de dados SQL e APIs externas |
75
75
  | **Orquestração de Fluxos** | Handoffs automáticos entre agentes conforme a complexidade da demanda |
76
+ | **Tom e Estilo Customizáveis** | AgentStyle para personalizar linguagem, tom e formato de respostas |
76
77
  | **Escalonamento Controlado** | Transferência para atendimento humano com contexto preservado |
77
78
  | **Gestão de Feedbacks** | Sistema de tickets para reclamações, sugestões e acompanhamento |
78
79
  | **Configuração Declarativa** | Personalização completa via arquivos YAML |
@@ -92,6 +93,7 @@ Plataforma que unifica múltiplos agentes especializados para resolver demandas
92
93
  - [Escalation Agent](#-escalation-agent)
93
94
  - [Feedback Agent](#-feedback-agent)
94
95
  - [Fluxo de Handoffs](#-fluxo-de-handoffs)
96
+ - [Estilo de Comunicação](#-estilo-de-comunicação-agentstyle)
95
97
  - [Tracing e Monitoramento](#-tracing-e-monitoramento)
96
98
  - [Suporte](#-suporte)
97
99
 
@@ -278,6 +280,7 @@ meu_cliente/
278
280
  ├── escalation_config.yaml # Recomendado
279
281
  ├── feedback_config.yaml # Recomendado
280
282
  ├── guardrails_config.yaml # Recomendado
283
+ ├── style_config.yaml # Opcional - Tom e estilo
281
284
  └── data/ # Dados estruturados (CSV, etc.)
282
285
  ```
283
286
 
@@ -596,6 +599,87 @@ network = create_standard_network(
596
599
 
597
600
  ---
598
601
 
602
+ ## 🎨 Estilo de Comunicação (AgentStyle)
603
+
604
+ Personalize o tom e estilo de resposta dos agentes:
605
+
606
+ ### Via Código
607
+
608
+ ```python
609
+ from pathlib import Path
610
+ from atendentepro import create_standard_network, AgentStyle
611
+
612
+ # Estilo global (aplicado a todos os agentes)
613
+ global_style = AgentStyle(
614
+ tone="profissional e consultivo",
615
+ language_style="formal", # formal, informal, neutro
616
+ response_length="moderado", # conciso, moderado, detalhado
617
+ custom_rules="Sempre cumprimente o usuário pelo nome.",
618
+ )
619
+
620
+ # Estilos específicos por agente
621
+ network = create_standard_network(
622
+ templates_root=Path("./meu_cliente"),
623
+ client="config",
624
+ global_style=global_style,
625
+ agent_styles={
626
+ "escalation": AgentStyle(
627
+ tone="empático e acolhedor",
628
+ custom_rules="Demonstre compreensão pela situação.",
629
+ ),
630
+ "knowledge": AgentStyle(
631
+ tone="didático e paciente",
632
+ response_length="detalhado",
633
+ ),
634
+ },
635
+ )
636
+ ```
637
+
638
+ ### Via YAML (style_config.yaml)
639
+
640
+ ```yaml
641
+ # Estilo Global
642
+ global:
643
+ tone: "profissional e cordial"
644
+ language_style: "formal"
645
+ response_length: "moderado"
646
+ custom_rules: |
647
+ - Seja objetivo e claro nas respostas
648
+ - Use linguagem inclusiva
649
+
650
+ # Estilos por Agente
651
+ agents:
652
+ escalation:
653
+ tone: "empático e tranquilizador"
654
+ custom_rules: |
655
+ - Demonstre compreensão pela situação
656
+ - Assegure que o problema será resolvido
657
+
658
+ knowledge:
659
+ tone: "didático e paciente"
660
+ response_length: "detalhado"
661
+ custom_rules: |
662
+ - Explique conceitos de forma acessível
663
+ - Cite as fontes das informações
664
+
665
+ feedback:
666
+ tone: "solícito e atencioso"
667
+ custom_rules: |
668
+ - Agradeça o feedback recebido
669
+ - Confirme o registro da solicitação
670
+ ```
671
+
672
+ ### Opções Disponíveis
673
+
674
+ | Parâmetro | Valores | Descrição |
675
+ |-----------|---------|-----------|
676
+ | `tone` | Texto livre | Tom da conversa (ex: "profissional", "empático") |
677
+ | `language_style` | `formal`, `informal`, `neutro` | Nível de formalidade |
678
+ | `response_length` | `conciso`, `moderado`, `detalhado` | Tamanho das respostas |
679
+ | `custom_rules` | Texto livre | Regras personalizadas |
680
+
681
+ ---
682
+
599
683
  ## 🔧 Dependências
600
684
 
601
685
  - Python 3.9+
@@ -709,7 +793,17 @@ configure_application_insights(
709
793
 
710
794
  ## 📝 Changelog
711
795
 
712
- ### v0.5.9 (Atual)
796
+ ### v0.6.1 (Atual)
797
+ - Documentação PyPI atualizada com AgentStyle e changelog completo
798
+
799
+ ### v0.6.0
800
+ - **AgentStyle**: Nova classe para personalizar tom e estilo de comunicação
801
+ - `tone`, `language_style`, `response_length`, `custom_rules`
802
+ - `style_config.yaml`: Configuração de estilos via YAML
803
+ - Parâmetros `global_style` e `agent_styles` em `create_standard_network()`
804
+ - Todos os agentes aceitam `style_instructions`
805
+
806
+ ### v0.5.9
713
807
  - Descrição PyPI formal: "Framework de orquestração de agentes IA"
714
808
  - README profissional com foco em capacidades corporativas
715
809
 
@@ -1,18 +1,18 @@
1
- atendentepro/README.md,sha256=AMVMJlVOlXcwU_kRGBiIoSn8hASLHrhZwxV1jr1LJsU,43012
2
- atendentepro/__init__.py,sha256=A7ANs1G18HZEhl-C_OVVdOzM0KCRDo-sX1Veq4IYwDo,5572
1
+ atendentepro/README.md,sha256=TAXl5GRjhSwz_I-Dx_eN5JOIcUxuE_dz31iMZ_-OnRY,45390
2
+ atendentepro/__init__.py,sha256=CDK61bxE18NYvLeswIoQWLarw2_xJAOEb2yONsQ2CqQ,5606
3
3
  atendentepro/license.py,sha256=rlPtysXNqAzEQkP2VjUAVu_nMndhPgfKv1yN2ruUYVI,17570
4
- atendentepro/network.py,sha256=s7h9if2oS_15BL8VoONjMlihEFCkJqdHxR5WFL81gl4,17310
4
+ atendentepro/network.py,sha256=1grEjYDZQ7K6r-eQ1tMV3g1vBAdkiNn0v1EeraqTK18,22341
5
5
  atendentepro/agents/__init__.py,sha256=OcPhG1Dp6xe49B5YIti4HVmaZDoDIrFLfRa8GmI4jpQ,1638
6
- atendentepro/agents/answer.py,sha256=dIZzGL_ddjC96JIiWSwDg33phwca8NpWFxO16FFYVoA,1905
7
- atendentepro/agents/confirmation.py,sha256=5Zg4z9A90CydYiEk8CEAKnnza71algFKF-N1WLwGDQI,2311
8
- atendentepro/agents/escalation.py,sha256=YNA2e1Si30FJoIJkpos3B9imaR_Q6uv9K2o-F-Ht8rQ,17190
9
- atendentepro/agents/feedback.py,sha256=xTFANEkFQaYIYQxlD6_hxTGAxfGUVwTM-rnfN0gT78Y,32996
10
- atendentepro/agents/flow.py,sha256=qWuPcjfm2peWjpHFUiq0P1blRk500LUUucb2Z9kT95Q,2056
11
- atendentepro/agents/interview.py,sha256=Tegfh3ZTr7__b_a0elyfn57u56yuS2pN_RB-8vOt-Os,2133
12
- atendentepro/agents/knowledge.py,sha256=M8XOJ_yxYRyuCaBxn-xFCCWE-MTx5bjyUi4-E2tSPL8,10080
13
- atendentepro/agents/onboarding.py,sha256=bDdwEE33Hcnv8UW3qsHhLcloaEL5xfh3BBeoWTgb8s0,2098
14
- atendentepro/agents/triage.py,sha256=VUHOwbQq0jt8pDfNy0FWznicqXDgMfXW0JwAsuGcAzg,1733
15
- atendentepro/agents/usage.py,sha256=hmckYQ4kOfYqu15xsxg_r2VoRozCwtw-RxxteUtbsI0,1594
6
+ atendentepro/agents/answer.py,sha256=Bwxhpeqp7bbiqHN3hfLwuF7wCekd0H2CI4H0UKMTDAY,2130
7
+ atendentepro/agents/confirmation.py,sha256=EB1vb_qBeZu9r0WKTe98kBHfdiuBzVaRUZmDpUIc7sc,2536
8
+ atendentepro/agents/escalation.py,sha256=ukFRNs0ISUug29IN2_wzIKUF_YKw5CCyGzkITtfdLx0,17415
9
+ atendentepro/agents/feedback.py,sha256=7afcdXmW6NfVKJcmZPWbRwD5yPOVOWbvVdqh0LaYfyE,33221
10
+ atendentepro/agents/flow.py,sha256=MLcumyoFFXqhkwu9lIURLJx_sSz-MZvwUdXRGW_PyXo,2281
11
+ atendentepro/agents/interview.py,sha256=vFYCEvtCoCwX7vMVaN5acXO6xKzuBA12jxrqA1SE6n8,2358
12
+ atendentepro/agents/knowledge.py,sha256=Lui1ZVC4AYOvzfm4G4vJZtaRNsXBTVlgfOSchBXryVE,10305
13
+ atendentepro/agents/onboarding.py,sha256=f7ezfZdL3o0o4mLoTpDLFoxUNeEcCKl80qQsxL7t7JI,2323
14
+ atendentepro/agents/triage.py,sha256=pdYCA5AqbGMY0WoJXvdceAz_gnQ7D_fJp7dxxsD-GDg,1958
15
+ atendentepro/agents/usage.py,sha256=wdxX7ZJVO6RGkuAY7JIgTfUQHid-q9U5ohLmvIg399c,1819
16
16
  atendentepro/config/__init__.py,sha256=LQZbEz9AVGnO8xCG_rI9GmyFQun5HQqo8hJkkm-d_e4,338
17
17
  atendentepro/config/settings.py,sha256=Z1texEtO76Rrt-wPyEXM3FyujDE75r8HbEEJClzFOvk,4762
18
18
  atendentepro/guardrails/__init__.py,sha256=lCSI4RbQeIOya8k1wIADoxz9gYySDtUtOv-JiXisvyQ,454
@@ -30,14 +30,14 @@ atendentepro/prompts/interview.py,sha256=9zVGA8zSmm6pBx2i1LPGNJIPuLlz7PZKRJE_PC6
30
30
  atendentepro/prompts/knowledge.py,sha256=B3BOyAvzQlwAkR51gc-B6XbQLtwIZlwGP1ofhZ4cFbk,4644
31
31
  atendentepro/prompts/onboarding.py,sha256=78fSIh2ifsGeoav8DV41_jnyU157c0dtggJujcDvW4U,6093
32
32
  atendentepro/prompts/triage.py,sha256=bSdEVheGy03r5P6MQuv7NwhN2_wrt0mK80F9f_LskRU,1283
33
- atendentepro/templates/__init__.py,sha256=kSXiDXVIZKKsSn2GuHBcHsnXqVRcNWyBzRlKl9HYoCI,1137
34
- atendentepro/templates/manager.py,sha256=KdE4khWDMD2S607TDTMkvJ8lZzQ9D_TD_lBaXYSTBzI,17932
33
+ atendentepro/templates/__init__.py,sha256=GbtNnhf2Zz-JiNReq-bBLzTdMZ-JFItmPU0OjnlU640,1267
34
+ atendentepro/templates/manager.py,sha256=kEeVRc1GHW5W8Q3GHgn6iBEvyzyO-GcEIKTBorYaHXw,21405
35
35
  atendentepro/utils/__init__.py,sha256=WCJ6_btsLaI6xxHXvNHNue-nKrXWTKscNZGTToQiJ8A,833
36
36
  atendentepro/utils/openai_client.py,sha256=R0ns7SU36vTgploq14-QJMTke1pPxcAXlENDeoHU0L4,4552
37
37
  atendentepro/utils/tracing.py,sha256=kpTPw1PF4rR1qq1RyBnAaPIQIJRka4RF8MfG_JrRJ7U,8486
38
- atendentepro-0.5.9.dist-info/licenses/LICENSE,sha256=TF6CdXxePoT9DXtPnCejiU5mUwWzrFzd1iyWJyoMauA,983
39
- atendentepro-0.5.9.dist-info/METADATA,sha256=bLx0WiUGtJ7p8rb095fRgp5N5txnwucdGsoQmHBxicY,22701
40
- atendentepro-0.5.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
41
- atendentepro-0.5.9.dist-info/entry_points.txt,sha256=OP0upzqJF3MLS6VX-M-5BfUwx5YLJO2sJ3YBAp4e6yI,89
42
- atendentepro-0.5.9.dist-info/top_level.txt,sha256=BFasD4SMmgDUmWKlTIZ1PeuukoRBhyiMIz8umKWVCcs,13
43
- atendentepro-0.5.9.dist-info/RECORD,,
38
+ atendentepro-0.6.1.dist-info/licenses/LICENSE,sha256=TF6CdXxePoT9DXtPnCejiU5mUwWzrFzd1iyWJyoMauA,983
39
+ atendentepro-0.6.1.dist-info/METADATA,sha256=xj9aGwN2-ErdDl02rgnKe-QWKFm5W2y_8ptfIs4xi7I,25518
40
+ atendentepro-0.6.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
41
+ atendentepro-0.6.1.dist-info/entry_points.txt,sha256=OP0upzqJF3MLS6VX-M-5BfUwx5YLJO2sJ3YBAp4e6yI,89
42
+ atendentepro-0.6.1.dist-info/top_level.txt,sha256=BFasD4SMmgDUmWKlTIZ1PeuukoRBhyiMIz8umKWVCcs,13
43
+ atendentepro-0.6.1.dist-info/RECORD,,