memra 0.2.13__py3-none-any.whl → 0.2.15__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.
- memra/cli.py +322 -51
- {memra-0.2.13.dist-info → memra-0.2.15.dist-info}/METADATA +1 -1
- {memra-0.2.13.dist-info → memra-0.2.15.dist-info}/RECORD +7 -61
- memra-0.2.15.dist-info/top_level.txt +1 -0
- memra-0.2.13.dist-info/top_level.txt +0 -4
- memra-ops/app.py +0 -808
- memra-ops/config/config.py +0 -25
- memra-ops/config.py +0 -34
- memra-ops/logic/__init__.py +0 -1
- memra-ops/logic/file_tools.py +0 -43
- memra-ops/logic/invoice_tools.py +0 -668
- memra-ops/logic/invoice_tools_fix.py +0 -66
- memra-ops/mcp_bridge_server.py +0 -1178
- memra-ops/scripts/check_database.py +0 -37
- memra-ops/scripts/clear_database.py +0 -48
- memra-ops/scripts/monitor_database.py +0 -67
- memra-ops/scripts/release.py +0 -133
- memra-ops/scripts/reset_database.py +0 -65
- memra-ops/scripts/start_memra.py +0 -334
- memra-ops/scripts/stop_memra.py +0 -132
- memra-ops/server_tool_registry.py +0 -190
- memra-ops/tests/test_llm_text_to_sql.py +0 -115
- memra-ops/tests/test_llm_vs_pattern.py +0 -130
- memra-ops/tests/test_mcp_schema_aware.py +0 -124
- memra-ops/tests/test_schema_aware_sql.py +0 -139
- memra-ops/tests/test_schema_aware_sql_simple.py +0 -66
- memra-ops/tests/test_text_to_sql_demo.py +0 -140
- memra-ops/tools/mcp_bridge_server.py +0 -851
- memra-sdk/examples/accounts_payable.py +0 -215
- memra-sdk/examples/accounts_payable_client.py +0 -217
- memra-sdk/examples/accounts_payable_mcp.py +0 -200
- memra-sdk/examples/ask_questions.py +0 -123
- memra-sdk/examples/invoice_processing.py +0 -116
- memra-sdk/examples/propane_delivery.py +0 -87
- memra-sdk/examples/simple_text_to_sql.py +0 -158
- memra-sdk/memra/__init__.py +0 -31
- memra-sdk/memra/discovery.py +0 -15
- memra-sdk/memra/discovery_client.py +0 -49
- memra-sdk/memra/execution.py +0 -481
- memra-sdk/memra/models.py +0 -99
- memra-sdk/memra/tool_registry.py +0 -343
- memra-sdk/memra/tool_registry_client.py +0 -106
- memra-sdk/scripts/release.py +0 -133
- memra-sdk/setup.py +0 -52
- memra-workflows/accounts_payable/accounts_payable.py +0 -215
- memra-workflows/accounts_payable/accounts_payable_client.py +0 -216
- memra-workflows/accounts_payable/accounts_payable_mcp.py +0 -200
- memra-workflows/accounts_payable/accounts_payable_smart.py +0 -221
- memra-workflows/invoice_processing/invoice_processing.py +0 -116
- memra-workflows/invoice_processing/smart_invoice_processor.py +0 -220
- memra-workflows/logic/__init__.py +0 -1
- memra-workflows/logic/file_tools.py +0 -50
- memra-workflows/logic/invoice_tools.py +0 -501
- memra-workflows/logic/propane_agents.py +0 -52
- memra-workflows/mcp_bridge_server.py +0 -230
- memra-workflows/propane_delivery/propane_delivery.py +0 -87
- memra-workflows/text_to_sql/complete_invoice_workflow_with_queries.py +0 -208
- memra-workflows/text_to_sql/complete_text_to_sql_system.py +0 -266
- memra-workflows/text_to_sql/file_discovery_demo.py +0 -156
- {memra-0.2.13.dist-info → memra-0.2.15.dist-info}/LICENSE +0 -0
- {memra-0.2.13.dist-info → memra-0.2.15.dist-info}/WHEEL +0 -0
- {memra-0.2.13.dist-info → memra-0.2.15.dist-info}/entry_points.txt +0 -0
@@ -1,215 +0,0 @@
|
|
1
|
-
from memra import Agent, Department, LLM
|
2
|
-
from memra.execution import ExecutionEngine
|
3
|
-
import sys
|
4
|
-
import os
|
5
|
-
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
6
|
-
from config import DEFAULT_LLM_CONFIG, AGENT_LLM_CONFIG
|
7
|
-
|
8
|
-
# Define LLMs for different agent types
|
9
|
-
default_llm = LLM(
|
10
|
-
model=DEFAULT_LLM_CONFIG["model"],
|
11
|
-
temperature=DEFAULT_LLM_CONFIG["temperature"],
|
12
|
-
max_tokens=DEFAULT_LLM_CONFIG["max_tokens"]
|
13
|
-
)
|
14
|
-
|
15
|
-
parsing_llm = LLM(
|
16
|
-
model=AGENT_LLM_CONFIG["parsing"]["model"],
|
17
|
-
temperature=AGENT_LLM_CONFIG["parsing"]["temperature"],
|
18
|
-
max_tokens=AGENT_LLM_CONFIG["parsing"]["max_tokens"]
|
19
|
-
)
|
20
|
-
|
21
|
-
manager_llm = LLM(
|
22
|
-
model=AGENT_LLM_CONFIG["manager"]["model"],
|
23
|
-
temperature=AGENT_LLM_CONFIG["manager"]["temperature"],
|
24
|
-
max_tokens=AGENT_LLM_CONFIG["manager"]["max_tokens"]
|
25
|
-
)
|
26
|
-
|
27
|
-
# Define the agents with their roles, jobs, tools, and systems
|
28
|
-
etl_agent = Agent(
|
29
|
-
role="Data Engineer",
|
30
|
-
job="Extract invoice schema from Postgres database",
|
31
|
-
llm=default_llm,
|
32
|
-
sops=[
|
33
|
-
"Connect to PostgresDB using credentials",
|
34
|
-
"Query information_schema for invoices table",
|
35
|
-
"Extract column names, types, and constraints",
|
36
|
-
"Return schema as structured JSON"
|
37
|
-
],
|
38
|
-
systems=["PostgresDB"],
|
39
|
-
tools=[
|
40
|
-
{"name": "DatabaseQueryTool", "hosted_by": "memra"}
|
41
|
-
],
|
42
|
-
output_key="invoice_schema"
|
43
|
-
)
|
44
|
-
|
45
|
-
# Fallback agent if schema extraction fails
|
46
|
-
schema_loader = Agent(
|
47
|
-
role="Schema Loader",
|
48
|
-
job="Load invoice schema from local file",
|
49
|
-
llm=default_llm,
|
50
|
-
sops=[
|
51
|
-
"Read schema file from disk",
|
52
|
-
"Validate schema format",
|
53
|
-
"Return parsed schema"
|
54
|
-
],
|
55
|
-
systems=["FileSystem"],
|
56
|
-
tools=[
|
57
|
-
{"name": "FileReader", "hosted_by": "memra"}
|
58
|
-
],
|
59
|
-
config={"path": "/local/dependencies/data_model.json"},
|
60
|
-
output_key="invoice_schema"
|
61
|
-
)
|
62
|
-
|
63
|
-
parser_agent = Agent(
|
64
|
-
role="Invoice Parser",
|
65
|
-
job="Extract structured data from invoice PDF using schema",
|
66
|
-
llm=parsing_llm, # Use specialized parsing LLM
|
67
|
-
sops=[
|
68
|
-
"Load invoice PDF file",
|
69
|
-
"Convert to high-contrast images if needed",
|
70
|
-
"Run OCR to extract text",
|
71
|
-
"Use schema to identify and extract fields",
|
72
|
-
"Validate extracted data against schema types",
|
73
|
-
"Return structured invoice data"
|
74
|
-
],
|
75
|
-
systems=["InvoiceStore"],
|
76
|
-
tools=[
|
77
|
-
{"name": "PDFProcessor", "hosted_by": "memra"},
|
78
|
-
{"name": "OCRTool", "hosted_by": "memra"},
|
79
|
-
{"name": "InvoiceExtractionWorkflow", "hosted_by": "memra"}
|
80
|
-
],
|
81
|
-
input_keys=["file", "invoice_schema"],
|
82
|
-
output_key="invoice_data"
|
83
|
-
)
|
84
|
-
|
85
|
-
writer_agent = Agent(
|
86
|
-
role="Data Entry Specialist",
|
87
|
-
job="Write validated invoice data to Postgres database",
|
88
|
-
llm=default_llm,
|
89
|
-
sops=[
|
90
|
-
"Validate invoice data completeness",
|
91
|
-
"Map fields to database columns using schema",
|
92
|
-
"Connect to PostgresDB",
|
93
|
-
"Insert record into invoices table",
|
94
|
-
"Return confirmation with record ID"
|
95
|
-
],
|
96
|
-
systems=["PostgresDB"],
|
97
|
-
tools=[
|
98
|
-
{"name": "DataValidator", "hosted_by": "memra"},
|
99
|
-
{"name": "PostgresInsert", "hosted_by": "memra"}
|
100
|
-
],
|
101
|
-
input_keys=["invoice_data", "invoice_schema"],
|
102
|
-
output_key="write_confirmation"
|
103
|
-
)
|
104
|
-
|
105
|
-
# Define the manager who oversees the workflow
|
106
|
-
manager_agent = Agent(
|
107
|
-
role="Accounts Payable Manager",
|
108
|
-
job="Coordinate invoice processing pipeline and handle exceptions",
|
109
|
-
llm=manager_llm, # Use specialized manager LLM
|
110
|
-
sops=[
|
111
|
-
"Check if schema extraction succeeded",
|
112
|
-
"If schema missing, delegate to Schema Loader",
|
113
|
-
"Validate parsed invoice has required fields",
|
114
|
-
"Ensure invoice total matches line items before DB write",
|
115
|
-
"Handle and log any errors with appropriate escalation"
|
116
|
-
],
|
117
|
-
allow_delegation=True,
|
118
|
-
fallback_agents={
|
119
|
-
"Data Engineer": "Schema Loader"
|
120
|
-
},
|
121
|
-
output_key="workflow_status"
|
122
|
-
)
|
123
|
-
|
124
|
-
# Create the department with all agents
|
125
|
-
ap_department = Department(
|
126
|
-
name="Accounts Payable",
|
127
|
-
mission="Process invoices accurately into financial system per company data standards",
|
128
|
-
agents=[etl_agent, schema_loader, parser_agent, writer_agent],
|
129
|
-
manager_agent=manager_agent,
|
130
|
-
workflow_order=["Data Engineer", "Invoice Parser", "Data Entry Specialist"],
|
131
|
-
dependencies=["PostgresDB", "InvoiceStore", "PaymentGateway"],
|
132
|
-
execution_policy={
|
133
|
-
"retry_on_fail": True,
|
134
|
-
"max_retries": 2,
|
135
|
-
"halt_on_validation_error": True,
|
136
|
-
"timeout_seconds": 300
|
137
|
-
},
|
138
|
-
context={
|
139
|
-
"company_id": "acme_corp",
|
140
|
-
"fiscal_year": "2024"
|
141
|
-
}
|
142
|
-
)
|
143
|
-
|
144
|
-
# Execute the department
|
145
|
-
engine = ExecutionEngine()
|
146
|
-
input_data = {
|
147
|
-
"file": "invoices/10352259310.PDF", # For development - users should update to their invoice path
|
148
|
-
"connection": "postgresql://your_username@localhost:5432/memra_invoice_db"
|
149
|
-
}
|
150
|
-
|
151
|
-
result = engine.execute_department(ap_department, input_data)
|
152
|
-
|
153
|
-
if result.success:
|
154
|
-
print("✅ Invoice processing completed successfully!")
|
155
|
-
|
156
|
-
# Show manager validation results
|
157
|
-
if 'workflow_status' in result.data:
|
158
|
-
manager_report = result.data['workflow_status']
|
159
|
-
print(f"\n🔍 Manager Validation Report:")
|
160
|
-
print(f"Status: {manager_report.get('validation_status', 'unknown')}")
|
161
|
-
print(f"Summary: {manager_report.get('summary', 'No summary available')}")
|
162
|
-
|
163
|
-
# Show agent performance analysis
|
164
|
-
if 'agent_performance' in manager_report:
|
165
|
-
print(f"\n📊 Agent Performance Analysis:")
|
166
|
-
for agent_role, performance in manager_report['agent_performance'].items():
|
167
|
-
work_quality = performance['work_quality']
|
168
|
-
status_emoji = "✅" if work_quality == "real" else "🔄"
|
169
|
-
print(f"{status_emoji} {agent_role}: {performance['status']}")
|
170
|
-
if performance['tools_real_work']:
|
171
|
-
print(f" Real work: {', '.join(performance['tools_real_work'])}")
|
172
|
-
if performance['tools_mock_work']:
|
173
|
-
print(f" Mock work: {', '.join(performance['tools_mock_work'])}")
|
174
|
-
|
175
|
-
# Show workflow analysis
|
176
|
-
if 'workflow_analysis' in manager_report:
|
177
|
-
analysis = manager_report['workflow_analysis']
|
178
|
-
print(f"\n📈 Workflow Analysis:")
|
179
|
-
print(f"Overall Quality: {analysis['overall_quality']}")
|
180
|
-
print(f"Real Work: {analysis['real_work_agents']}/{analysis['total_agents']} agents ({analysis['real_work_percentage']:.1f}%)")
|
181
|
-
|
182
|
-
# Show recommendations
|
183
|
-
if 'recommendations' in manager_report and manager_report['recommendations']:
|
184
|
-
print(f"\n💡 Recommendations:")
|
185
|
-
for rec in manager_report['recommendations']:
|
186
|
-
print(f" • {rec}")
|
187
|
-
|
188
|
-
# Try to get record_id if it exists
|
189
|
-
if result.data and 'write_confirmation' in result.data:
|
190
|
-
confirmation = result.data['write_confirmation']
|
191
|
-
if isinstance(confirmation, dict) and 'record_id' in confirmation:
|
192
|
-
print(f"\n💾 Invoice processed successfully: Record ID {confirmation['record_id']}")
|
193
|
-
else:
|
194
|
-
print(f"\n💾 Write confirmation: {confirmation}")
|
195
|
-
|
196
|
-
# Show execution trace
|
197
|
-
print("\n=== Execution Trace ===")
|
198
|
-
print(f"Agents executed: {', '.join(result.trace.agents_executed)}")
|
199
|
-
print(f"Tools invoked: {', '.join(result.trace.tools_invoked)}")
|
200
|
-
if result.trace.errors:
|
201
|
-
print(f"Errors: {', '.join(result.trace.errors)}")
|
202
|
-
else:
|
203
|
-
print(f"❌ Processing failed: {result.error}")
|
204
|
-
print("\n=== Execution Trace ===")
|
205
|
-
print(f"Agents executed: {', '.join(result.trace.agents_executed)}")
|
206
|
-
print(f"Tools invoked: {', '.join(result.trace.tools_invoked)}")
|
207
|
-
print(f"Errors: {', '.join(result.trace.errors)}")
|
208
|
-
|
209
|
-
# Show audit information
|
210
|
-
audit = engine.get_last_audit()
|
211
|
-
if audit:
|
212
|
-
print(f"\n=== Audit ===")
|
213
|
-
print(f"Agents executed: {audit.agents_run}")
|
214
|
-
print(f"Tools used: {audit.tools_invoked}")
|
215
|
-
print(f"Total duration: {audit.duration_seconds:.1f}s")
|
@@ -1,216 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Client-side Accounts Payable Example
|
3
|
-
This version calls the Memra API hosted on Fly.io instead of running tools locally
|
4
|
-
"""
|
5
|
-
|
6
|
-
import os
|
7
|
-
from memra import Agent, Department, LLM, check_api_health, get_api_status
|
8
|
-
from memra.execution import ExecutionEngine
|
9
|
-
import sys
|
10
|
-
|
11
|
-
# Check for required API key
|
12
|
-
if not os.getenv("MEMRA_API_KEY"):
|
13
|
-
print("❌ Error: MEMRA_API_KEY environment variable is required")
|
14
|
-
print("Please set your API key: export MEMRA_API_KEY='your-key-here'")
|
15
|
-
print("Contact info@memra.co for API access")
|
16
|
-
sys.exit(1)
|
17
|
-
|
18
|
-
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
19
|
-
from config import DEFAULT_LLM_CONFIG, AGENT_LLM_CONFIG
|
20
|
-
|
21
|
-
# Set API configuration
|
22
|
-
os.environ["MEMRA_API_URL"] = "https://api.memra.co" # Use production API
|
23
|
-
|
24
|
-
# Check API health before starting
|
25
|
-
print("🔍 Checking Memra API status...")
|
26
|
-
api_status = get_api_status()
|
27
|
-
print(f"API Health: {'✅ Healthy' if api_status['api_healthy'] else '❌ Unavailable'}")
|
28
|
-
print(f"API URL: {api_status['api_url']}")
|
29
|
-
print(f"Tools Available: {api_status['tools_available']}")
|
30
|
-
|
31
|
-
if not api_status['api_healthy']:
|
32
|
-
print("❌ Cannot proceed - Memra API is not available")
|
33
|
-
print("Make sure the API server is running on localhost:8080")
|
34
|
-
exit(1)
|
35
|
-
|
36
|
-
# Define LLMs (these are just metadata - actual LLM calls happen on the server)
|
37
|
-
default_llm = LLM(
|
38
|
-
model="llama-3.2-11b-vision-preview",
|
39
|
-
temperature=0.1,
|
40
|
-
max_tokens=2000
|
41
|
-
)
|
42
|
-
|
43
|
-
parsing_llm = LLM(
|
44
|
-
model="llama-3.2-11b-vision-preview",
|
45
|
-
temperature=0.0,
|
46
|
-
max_tokens=4000
|
47
|
-
)
|
48
|
-
|
49
|
-
manager_llm = LLM(
|
50
|
-
model="llama-3.2-11b-vision-preview",
|
51
|
-
temperature=0.2,
|
52
|
-
max_tokens=1000
|
53
|
-
)
|
54
|
-
|
55
|
-
# Define agents (same declarative interface as before)
|
56
|
-
etl_agent = Agent(
|
57
|
-
role="Data Engineer",
|
58
|
-
job="Extract invoice schema from database",
|
59
|
-
llm=default_llm,
|
60
|
-
sops=[
|
61
|
-
"Connect to database using credentials",
|
62
|
-
"Query information_schema for invoices table",
|
63
|
-
"Extract column names, types, and constraints",
|
64
|
-
"Return schema as structured JSON"
|
65
|
-
],
|
66
|
-
systems=["Database"],
|
67
|
-
tools=[
|
68
|
-
{"name": "DatabaseQueryTool", "hosted_by": "memra"}
|
69
|
-
],
|
70
|
-
output_key="invoice_schema"
|
71
|
-
)
|
72
|
-
|
73
|
-
parser_agent = Agent(
|
74
|
-
role="Invoice Parser",
|
75
|
-
job="Extract structured data from invoice PDF using schema",
|
76
|
-
llm=parsing_llm,
|
77
|
-
sops=[
|
78
|
-
"Load invoice PDF file",
|
79
|
-
"Send to vision model for field extraction",
|
80
|
-
"Validate extracted data against schema types",
|
81
|
-
"Return structured invoice data"
|
82
|
-
],
|
83
|
-
systems=["InvoiceStore"],
|
84
|
-
tools=[
|
85
|
-
{"name": "PDFProcessor", "hosted_by": "memra"},
|
86
|
-
{"name": "InvoiceExtractionWorkflow", "hosted_by": "memra"}
|
87
|
-
],
|
88
|
-
input_keys=["file", "invoice_schema"],
|
89
|
-
output_key="invoice_data"
|
90
|
-
)
|
91
|
-
|
92
|
-
writer_agent = Agent(
|
93
|
-
role="Data Entry Specialist",
|
94
|
-
job="Write validated invoice data to database",
|
95
|
-
llm=default_llm,
|
96
|
-
sops=[
|
97
|
-
"Validate invoice data completeness",
|
98
|
-
"Map fields to database columns using schema",
|
99
|
-
"Connect to database",
|
100
|
-
"Insert record into invoices table",
|
101
|
-
"Return confirmation with record ID"
|
102
|
-
],
|
103
|
-
systems=["Database"],
|
104
|
-
tools=[
|
105
|
-
{"name": "DataValidator", "hosted_by": "mcp"},
|
106
|
-
{"name": "PostgresInsert", "hosted_by": "mcp"}
|
107
|
-
],
|
108
|
-
input_keys=["invoice_data", "invoice_schema"],
|
109
|
-
output_key="write_confirmation"
|
110
|
-
)
|
111
|
-
|
112
|
-
manager_agent = Agent(
|
113
|
-
role="Accounts Payable Manager",
|
114
|
-
job="Coordinate invoice processing pipeline and handle exceptions",
|
115
|
-
llm=manager_llm,
|
116
|
-
sops=[
|
117
|
-
"Check if schema extraction succeeded",
|
118
|
-
"Validate parsed invoice has required fields",
|
119
|
-
"Ensure invoice total matches line items before DB write",
|
120
|
-
"Handle and log any errors with appropriate escalation"
|
121
|
-
],
|
122
|
-
allow_delegation=True,
|
123
|
-
output_key="workflow_status"
|
124
|
-
)
|
125
|
-
|
126
|
-
# Create department
|
127
|
-
ap_department = Department(
|
128
|
-
name="Accounts Payable",
|
129
|
-
mission="Process invoices accurately into financial system per company data standards",
|
130
|
-
agents=[etl_agent, parser_agent, writer_agent],
|
131
|
-
manager_agent=manager_agent,
|
132
|
-
workflow_order=["Data Engineer", "Invoice Parser", "Data Entry Specialist"],
|
133
|
-
dependencies=["Database", "InvoiceStore"],
|
134
|
-
execution_policy={
|
135
|
-
"retry_on_fail": True,
|
136
|
-
"max_retries": 2,
|
137
|
-
"halt_on_validation_error": True,
|
138
|
-
"timeout_seconds": 300
|
139
|
-
},
|
140
|
-
context={
|
141
|
-
"company_id": "acme_corp",
|
142
|
-
"fiscal_year": "2024",
|
143
|
-
"mcp_bridge_url": "http://localhost:8081",
|
144
|
-
"mcp_bridge_secret": "test-secret-for-development"
|
145
|
-
}
|
146
|
-
)
|
147
|
-
|
148
|
-
# Execute the department (tools will run on Fly.io)
|
149
|
-
print("\n🚀 Starting invoice processing workflow...")
|
150
|
-
print("📡 Tools will execute on Memra API server")
|
151
|
-
|
152
|
-
engine = ExecutionEngine()
|
153
|
-
input_data = {
|
154
|
-
"file": "invoices/10352259310.PDF", # For development - users should update to their invoice path
|
155
|
-
"connection": "postgresql://memra:memra123@localhost:5432/memra_invoice_db"
|
156
|
-
}
|
157
|
-
|
158
|
-
result = engine.execute_department(ap_department, input_data)
|
159
|
-
|
160
|
-
# Display results (same as before)
|
161
|
-
if result.success:
|
162
|
-
print("✅ Invoice processing completed successfully!")
|
163
|
-
|
164
|
-
# Show manager validation results
|
165
|
-
if 'workflow_status' in result.data:
|
166
|
-
manager_report = result.data['workflow_status']
|
167
|
-
print(f"\n🔍 Manager Validation Report:")
|
168
|
-
print(f"Status: {manager_report.get('validation_status', 'unknown')}")
|
169
|
-
print(f"Summary: {manager_report.get('summary', 'No summary available')}")
|
170
|
-
|
171
|
-
# Show agent performance analysis
|
172
|
-
if 'agent_performance' in manager_report:
|
173
|
-
print(f"\n📊 Agent Performance Analysis:")
|
174
|
-
for agent_role, performance in manager_report['agent_performance'].items():
|
175
|
-
work_quality = performance['work_quality']
|
176
|
-
status_emoji = "✅" if work_quality == "real" else "🔄"
|
177
|
-
print(f"{status_emoji} {agent_role}: {performance['status']}")
|
178
|
-
if performance['tools_real_work']:
|
179
|
-
print(f" Real work: {', '.join(performance['tools_real_work'])}")
|
180
|
-
if performance['tools_mock_work']:
|
181
|
-
print(f" Mock work: {', '.join(performance['tools_mock_work'])}")
|
182
|
-
|
183
|
-
# Show workflow analysis
|
184
|
-
if 'workflow_analysis' in manager_report:
|
185
|
-
analysis = manager_report['workflow_analysis']
|
186
|
-
print(f"\n📈 Workflow Analysis:")
|
187
|
-
print(f"Overall Quality: {analysis['overall_quality']}")
|
188
|
-
print(f"Real Work: {analysis['real_work_agents']}/{analysis['total_agents']} agents ({analysis['real_work_percentage']:.1f}%)")
|
189
|
-
|
190
|
-
# Show recommendations
|
191
|
-
if 'recommendations' in manager_report and manager_report['recommendations']:
|
192
|
-
print(f"\n💡 Recommendations:")
|
193
|
-
for rec in manager_report['recommendations']:
|
194
|
-
print(f" • {rec}")
|
195
|
-
|
196
|
-
# Try to get record_id if it exists
|
197
|
-
if result.data and 'write_confirmation' in result.data:
|
198
|
-
confirmation = result.data['write_confirmation']
|
199
|
-
if isinstance(confirmation, dict) and 'record_id' in confirmation:
|
200
|
-
print(f"\n💾 Invoice processed successfully: Record ID {confirmation['record_id']}")
|
201
|
-
else:
|
202
|
-
print(f"\n💾 Write confirmation: {confirmation}")
|
203
|
-
|
204
|
-
print(f"\n📡 All tools executed remotely on Memra API server")
|
205
|
-
|
206
|
-
else:
|
207
|
-
print(f"❌ Processing failed: {result.error}")
|
208
|
-
|
209
|
-
# Show execution trace
|
210
|
-
print("\n=== Execution Trace ===")
|
211
|
-
print(f"Agents executed: {', '.join(result.trace.agents_executed)}")
|
212
|
-
print(f"Tools invoked: {', '.join(result.trace.tools_invoked)}")
|
213
|
-
if result.trace.errors:
|
214
|
-
print(f"Errors: {', '.join(result.trace.errors)}")
|
215
|
-
|
216
|
-
print(f"\n🌐 API Calls made to: {api_status['api_url']}")
|
@@ -1,200 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
Accounts Payable Example with MCP Integration
|
4
|
-
This example demonstrates using MCP tools for database operations
|
5
|
-
"""
|
6
|
-
|
7
|
-
import os
|
8
|
-
import sys
|
9
|
-
import logging
|
10
|
-
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
11
|
-
|
12
|
-
from memra import Agent, Department
|
13
|
-
from memra.execution import ExecutionEngine
|
14
|
-
|
15
|
-
# Set up environment
|
16
|
-
os.environ['MEMRA_API_KEY'] = 'memra-prod-2024-001'
|
17
|
-
# Note: MEMRA_API_URL defaults to https://api.memra.co if not set
|
18
|
-
|
19
|
-
# Set up logging
|
20
|
-
logging.basicConfig(level=logging.INFO)
|
21
|
-
logger = logging.getLogger(__name__)
|
22
|
-
|
23
|
-
# Define the agents - using MCP for database operations
|
24
|
-
etl_agent = Agent(
|
25
|
-
role="Data Engineer",
|
26
|
-
job="Extract invoice schema from Postgres database",
|
27
|
-
sops=[
|
28
|
-
"Connect to PostgresDB using credentials",
|
29
|
-
"Query information_schema for invoices table",
|
30
|
-
"Extract column names, types, and constraints",
|
31
|
-
"Return schema as structured JSON"
|
32
|
-
],
|
33
|
-
systems=["PostgresDB"],
|
34
|
-
tools=[
|
35
|
-
{"name": "DatabaseQueryTool", "hosted_by": "memra"}
|
36
|
-
],
|
37
|
-
output_key="invoice_schema"
|
38
|
-
)
|
39
|
-
|
40
|
-
parser_agent = Agent(
|
41
|
-
role="Invoice Parser",
|
42
|
-
job="Extract structured data from invoice PDF using schema",
|
43
|
-
sops=[
|
44
|
-
"Load invoice PDF file",
|
45
|
-
"Convert to high-contrast images if needed",
|
46
|
-
"Run OCR to extract text",
|
47
|
-
"Use schema to identify and extract fields",
|
48
|
-
"Validate extracted data against schema types",
|
49
|
-
"Return structured invoice data"
|
50
|
-
],
|
51
|
-
systems=["InvoiceStore"],
|
52
|
-
tools=[
|
53
|
-
{"name": "PDFProcessor", "hosted_by": "memra"},
|
54
|
-
{"name": "OCRTool", "hosted_by": "memra"},
|
55
|
-
{"name": "InvoiceExtractionWorkflow", "hosted_by": "memra"}
|
56
|
-
],
|
57
|
-
input_keys=["file", "invoice_schema"],
|
58
|
-
output_key="invoice_data"
|
59
|
-
)
|
60
|
-
|
61
|
-
# THIS IS THE KEY CHANGE: Using MCP tools for database operations
|
62
|
-
writer_agent = Agent(
|
63
|
-
role="Data Entry Specialist",
|
64
|
-
job="Write validated invoice data to Postgres database via MCP",
|
65
|
-
sops=[
|
66
|
-
"Validate invoice data completeness",
|
67
|
-
"Map fields to database columns using schema",
|
68
|
-
"Use MCP bridge to connect to PostgresDB",
|
69
|
-
"Insert record into invoices table via MCP",
|
70
|
-
"Return confirmation with record ID"
|
71
|
-
],
|
72
|
-
systems=["PostgresDB"],
|
73
|
-
tools=[
|
74
|
-
{
|
75
|
-
"name": "DataValidator",
|
76
|
-
"hosted_by": "mcp",
|
77
|
-
"config": {
|
78
|
-
"bridge_url": "http://localhost:8081",
|
79
|
-
"bridge_secret": "test-secret-for-development"
|
80
|
-
}
|
81
|
-
},
|
82
|
-
{
|
83
|
-
"name": "PostgresInsert",
|
84
|
-
"hosted_by": "mcp",
|
85
|
-
"config": {
|
86
|
-
"bridge_url": "http://localhost:8081",
|
87
|
-
"bridge_secret": "test-secret-for-development"
|
88
|
-
}
|
89
|
-
}
|
90
|
-
],
|
91
|
-
input_keys=["invoice_data", "invoice_schema"],
|
92
|
-
output_key="write_confirmation"
|
93
|
-
)
|
94
|
-
|
95
|
-
# Define the manager
|
96
|
-
manager_agent = Agent(
|
97
|
-
role="Accounts Payable Manager",
|
98
|
-
job="Coordinate invoice processing pipeline and handle exceptions",
|
99
|
-
sops=[
|
100
|
-
"Check if schema extraction succeeded",
|
101
|
-
"Validate parsed invoice has required fields",
|
102
|
-
"Ensure invoice total matches line items before DB write",
|
103
|
-
"Handle and log any errors with appropriate escalation"
|
104
|
-
],
|
105
|
-
allow_delegation=True,
|
106
|
-
output_key="workflow_status"
|
107
|
-
)
|
108
|
-
|
109
|
-
# Create the department
|
110
|
-
ap_department = Department(
|
111
|
-
name="Accounts Payable with MCP",
|
112
|
-
mission="Process invoices accurately into financial system using MCP bridge",
|
113
|
-
agents=[etl_agent, parser_agent, writer_agent],
|
114
|
-
manager_agent=manager_agent,
|
115
|
-
workflow_order=["Data Engineer", "Invoice Parser", "Data Entry Specialist"],
|
116
|
-
dependencies=["PostgresDB", "InvoiceStore"],
|
117
|
-
execution_policy={
|
118
|
-
"retry_on_fail": True,
|
119
|
-
"max_retries": 2,
|
120
|
-
"halt_on_validation_error": True,
|
121
|
-
"timeout_seconds": 300
|
122
|
-
},
|
123
|
-
context={
|
124
|
-
"company_id": "acme_corp",
|
125
|
-
"fiscal_year": "2024"
|
126
|
-
}
|
127
|
-
)
|
128
|
-
|
129
|
-
def main():
|
130
|
-
print("🧪 Testing Accounts Payable with MCP Integration")
|
131
|
-
print("=" * 60)
|
132
|
-
|
133
|
-
# Create execution engine
|
134
|
-
engine = ExecutionEngine()
|
135
|
-
|
136
|
-
# Execute the department
|
137
|
-
input_data = {
|
138
|
-
"file": "invoices/10352259310.PDF", # For development - users should update to their invoice path
|
139
|
-
"connection": "postgresql://tarpus@localhost:5432/memra_invoice_db"
|
140
|
-
}
|
141
|
-
|
142
|
-
result = engine.execute_department(ap_department, input_data)
|
143
|
-
|
144
|
-
if result.success:
|
145
|
-
print("✅ Invoice processing completed successfully!")
|
146
|
-
|
147
|
-
# Show manager validation results
|
148
|
-
if 'workflow_status' in result.data:
|
149
|
-
manager_report = result.data['workflow_status']
|
150
|
-
print(f"\n🔍 Manager Validation Report:")
|
151
|
-
print(f"Status: {manager_report.get('validation_status', 'unknown')}")
|
152
|
-
print(f"Summary: {manager_report.get('summary', 'No summary available')}")
|
153
|
-
|
154
|
-
# Show agent performance analysis
|
155
|
-
if 'agent_performance' in manager_report:
|
156
|
-
print(f"\n📊 Agent Performance Analysis:")
|
157
|
-
for agent_role, performance in manager_report['agent_performance'].items():
|
158
|
-
work_quality = performance['work_quality']
|
159
|
-
status_emoji = "✅" if work_quality == "real" else "🔄"
|
160
|
-
print(f"{status_emoji} {agent_role}: {performance['status']}")
|
161
|
-
if performance['tools_real_work']:
|
162
|
-
print(f" Real work: {', '.join(performance['tools_real_work'])}")
|
163
|
-
if performance['tools_mock_work']:
|
164
|
-
print(f" Mock work: {', '.join(performance['tools_mock_work'])}")
|
165
|
-
|
166
|
-
# Show workflow analysis
|
167
|
-
if 'workflow_analysis' in manager_report:
|
168
|
-
analysis = manager_report['workflow_analysis']
|
169
|
-
print(f"\n📈 Workflow Analysis:")
|
170
|
-
print(f"Overall Quality: {analysis['overall_quality']}")
|
171
|
-
print(f"Real Work: {analysis['real_work_agents']}/{analysis['total_agents']} agents ({analysis['real_work_percentage']:.1f}%)")
|
172
|
-
|
173
|
-
# Try to get record_id if it exists
|
174
|
-
if result.data and 'write_confirmation' in result.data:
|
175
|
-
confirmation = result.data['write_confirmation']
|
176
|
-
print(f"\n💾 Write confirmation: {confirmation}")
|
177
|
-
|
178
|
-
# Show execution trace
|
179
|
-
print("\n=== Execution Trace ===")
|
180
|
-
print(f"Agents executed: {', '.join(result.trace.agents_executed)}")
|
181
|
-
print(f"Tools invoked: {', '.join(result.trace.tools_invoked)}")
|
182
|
-
if result.trace.errors:
|
183
|
-
print(f"Errors: {', '.join(result.trace.errors)}")
|
184
|
-
else:
|
185
|
-
print(f"❌ Processing failed: {result.error}")
|
186
|
-
print("\n=== Execution Trace ===")
|
187
|
-
print(f"Agents executed: {', '.join(result.trace.agents_executed)}")
|
188
|
-
print(f"Tools invoked: {', '.join(result.trace.tools_invoked)}")
|
189
|
-
print(f"Errors: {', '.join(result.trace.errors)}")
|
190
|
-
|
191
|
-
# Show audit information
|
192
|
-
audit = engine.get_last_audit()
|
193
|
-
if audit:
|
194
|
-
print(f"\n=== Audit ===")
|
195
|
-
print(f"Agents executed: {audit.agents_run}")
|
196
|
-
print(f"Tools used: {audit.tools_invoked}")
|
197
|
-
print(f"Total duration: {audit.duration_seconds:.1f}s")
|
198
|
-
|
199
|
-
if __name__ == "__main__":
|
200
|
-
main()
|