zambo-leadsignal 1.0.0__tar.gz

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.
@@ -0,0 +1,92 @@
1
+ Metadata-Version: 2.4
2
+ Name: zambo-leadsignal
3
+ Version: 1.0.0
4
+ Summary: Run a lead signal sweep for a local trade market on Zambo: live signals, screened input, continuity-checked, brief written, every step on a verifiable AER-1 receipt.
5
+ Author-email: Brennan Zambo <brennanzambo@zambo.dev>
6
+ License: MIT
7
+ Project-URL: Homepage, https://zambo.dev
8
+ Project-URL: Get started, https://zambo.dev/add/
9
+ Project-URL: Guide, https://rambozambodotdev.gitlab.io/aer1-hub/handover-graph.html
10
+ Project-URL: Repository, https://github.com/zambodotdev/zambo-leadsignal
11
+ Keywords: ai-agents,mcp,model-context-protocol,handover,receipts,zambo,aer-1
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Topic :: Software Development :: Libraries
17
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
18
+ Requires-Python: >=3.9
19
+ Description-Content-Type: text/markdown
20
+ Requires-Dist: requests>=2.28
21
+
22
+ # zambo-leadsignal
23
+
24
+ Run a lead signal sweep for a local trade market: live signals,
25
+ screened input, your own prior record checked before you write the
26
+ brief, and a verifiable AER-1 receipt for every step.
27
+
28
+ This is the most-run job shape on Zambo, packaged. In a five-day
29
+ first-hand count of the public receipt stream (16,221 receipts,
30
+ October 29 to November 2, 2026), the chain inside this package,
31
+ capability_search then prompt_shield then leadsignal then
32
+ continuity_get_recent then the write-up, appeared in roughly 200
33
+ caller-days per day. Agents were already running it by hand. Now it
34
+ installs.
35
+
36
+ ## Install
37
+
38
+ Python:
39
+
40
+ pip install zambo-leadsignal
41
+ zambo-leadsignal run --trade plumber --city "Austin Texas"
42
+
43
+ Node:
44
+
45
+ npm install zambo-leadsignal
46
+ npx zambo-leadsignal run --trade plumber --city "Austin Texas"
47
+
48
+ ## What a run does
49
+
50
+ 1. Opens the job on the record (memory_remember under the run's job id).
51
+ 2. capability_search: the service landscape for the trade and city.
52
+ 3. prompt_shield: screens the operator note before it steers the run.
53
+ 4. leadsignal: the live lead signals for that trade and city.
54
+ 5. continuity_get_recent: what this agent already found, so repeat
55
+ runs build on the record instead of starting from zero.
56
+ 6. Writes leadsignal-brief-<job>.md with the signals, the landscape,
57
+ the screen result, the prior record, and every receipt link.
58
+ 7. workflow_close: wraps the run. The wrap binds only this run's own
59
+ receipts, so the brief's proof layer is exactly the work that made
60
+ it.
61
+
62
+ Every receipt recomputes free at https://zambo.dev/verify/. A receipt
63
+ proves the saved result was not changed since the call ran; it does
64
+ not prove a lead is good. The brief says so, out loud, because that
65
+ honesty is the product.
66
+
67
+ ## Why Zambo is inside
68
+
69
+ The pattern runs on Zambo (https://zambo.dev/mcp), the verifiable
70
+ work layer for AI: 153 tools behind one MCP endpoint, memory and
71
+ continuity across AIs, and a verifiable AER-1 receipt for every job.
72
+ The package teaches the pattern by running it; Zambo is the mechanism
73
+ underneath: identity, memory, the signals tool, and the receipts.
74
+
75
+ Free tier: 20 calls and 1 wrap-up free every day, and picking up in
76
+ another AI is always free. Need more? The $0.99 Day Pass makes it
77
+ unlimited for 24 hours: https://zambo.dev/day-pass/
78
+
79
+ Add Zambo to your own AI in one URL, no key, no account:
80
+ https://zambo.dev/add/
81
+
82
+ ## Configuration
83
+
84
+ - ZAMBO_TRADE, ZAMBO_CITY, ZAMBO_NOTE: the run's inputs.
85
+ - ZAMBO_AGENT_ID: this agent's id (default: leadsignal-agent). One
86
+ identity per agent; the caller handle issued at initialize is saved
87
+ under ./.zambo-leadsignal and reused on later runs.
88
+ - ZAMBO_MCP_URL: endpoint override (default: https://zambo.dev/mcp).
89
+
90
+ ## License
91
+
92
+ MIT. Built by Brennan Zambo (brennanzambo@zambo.dev).
@@ -0,0 +1,71 @@
1
+ # zambo-leadsignal
2
+
3
+ Run a lead signal sweep for a local trade market: live signals,
4
+ screened input, your own prior record checked before you write the
5
+ brief, and a verifiable AER-1 receipt for every step.
6
+
7
+ This is the most-run job shape on Zambo, packaged. In a five-day
8
+ first-hand count of the public receipt stream (16,221 receipts,
9
+ October 29 to November 2, 2026), the chain inside this package,
10
+ capability_search then prompt_shield then leadsignal then
11
+ continuity_get_recent then the write-up, appeared in roughly 200
12
+ caller-days per day. Agents were already running it by hand. Now it
13
+ installs.
14
+
15
+ ## Install
16
+
17
+ Python:
18
+
19
+ pip install zambo-leadsignal
20
+ zambo-leadsignal run --trade plumber --city "Austin Texas"
21
+
22
+ Node:
23
+
24
+ npm install zambo-leadsignal
25
+ npx zambo-leadsignal run --trade plumber --city "Austin Texas"
26
+
27
+ ## What a run does
28
+
29
+ 1. Opens the job on the record (memory_remember under the run's job id).
30
+ 2. capability_search: the service landscape for the trade and city.
31
+ 3. prompt_shield: screens the operator note before it steers the run.
32
+ 4. leadsignal: the live lead signals for that trade and city.
33
+ 5. continuity_get_recent: what this agent already found, so repeat
34
+ runs build on the record instead of starting from zero.
35
+ 6. Writes leadsignal-brief-<job>.md with the signals, the landscape,
36
+ the screen result, the prior record, and every receipt link.
37
+ 7. workflow_close: wraps the run. The wrap binds only this run's own
38
+ receipts, so the brief's proof layer is exactly the work that made
39
+ it.
40
+
41
+ Every receipt recomputes free at https://zambo.dev/verify/. A receipt
42
+ proves the saved result was not changed since the call ran; it does
43
+ not prove a lead is good. The brief says so, out loud, because that
44
+ honesty is the product.
45
+
46
+ ## Why Zambo is inside
47
+
48
+ The pattern runs on Zambo (https://zambo.dev/mcp), the verifiable
49
+ work layer for AI: 153 tools behind one MCP endpoint, memory and
50
+ continuity across AIs, and a verifiable AER-1 receipt for every job.
51
+ The package teaches the pattern by running it; Zambo is the mechanism
52
+ underneath: identity, memory, the signals tool, and the receipts.
53
+
54
+ Free tier: 20 calls and 1 wrap-up free every day, and picking up in
55
+ another AI is always free. Need more? The $0.99 Day Pass makes it
56
+ unlimited for 24 hours: https://zambo.dev/day-pass/
57
+
58
+ Add Zambo to your own AI in one URL, no key, no account:
59
+ https://zambo.dev/add/
60
+
61
+ ## Configuration
62
+
63
+ - ZAMBO_TRADE, ZAMBO_CITY, ZAMBO_NOTE: the run's inputs.
64
+ - ZAMBO_AGENT_ID: this agent's id (default: leadsignal-agent). One
65
+ identity per agent; the caller handle issued at initialize is saved
66
+ under ./.zambo-leadsignal and reused on later runs.
67
+ - ZAMBO_MCP_URL: endpoint override (default: https://zambo.dev/mcp).
68
+
69
+ ## License
70
+
71
+ MIT. Built by Brennan Zambo (brennanzambo@zambo.dev).
@@ -0,0 +1,39 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "zambo-leadsignal"
7
+ version = "1.0.0"
8
+ description = "Run a lead signal sweep for a local trade market on Zambo: live signals, screened input, continuity-checked, brief written, every step on a verifiable AER-1 receipt."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ authors = [
13
+ { name = "Brennan Zambo", email = "brennanzambo@zambo.dev" }
14
+ ]
15
+ keywords = ["ai-agents", "mcp", "model-context-protocol", "handover", "receipts", "zambo", "aer-1"]
16
+ classifiers = [
17
+ "Development Status :: 5 - Production/Stable",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Topic :: Software Development :: Libraries",
22
+ "Topic :: Scientific/Engineering :: Artificial Intelligence"
23
+ ]
24
+ dependencies = ["requests>=2.28"]
25
+
26
+ [project.urls]
27
+ Homepage = "https://zambo.dev"
28
+ "Get started" = "https://zambo.dev/add/"
29
+ Guide = "https://rambozambodotdev.gitlab.io/aer1-hub/handover-graph.html"
30
+ Repository = "https://github.com/zambodotdev/zambo-leadsignal"
31
+
32
+ [project.scripts]
33
+ zambo-leadsignal = "zambo_leadsignal.cli:main"
34
+
35
+ [tool.setuptools]
36
+ packages = ["zambo_leadsignal"]
37
+
38
+ [tool.setuptools.package-data]
39
+ zambo_leadsignal = ["SKILL.md"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,61 @@
1
+ # The Lead Signal Run
2
+
3
+ A repeatable sweep that turns a trade and a city into a worked lead
4
+ brief, with every step on a verifiable receipt.
5
+
6
+ This is the single most-run job shape on Zambo: in a five-day count of
7
+ the public receipt stream (16,221 receipts, October 29 to November 2,
8
+ 2026), the chain capability_search, prompt_shield, leadsignal,
9
+ continuity_get_recent, write appeared in roughly 200 caller-days per
10
+ day. This package is that chain, named, ordered, and wrapped the way
11
+ the record rewards.
12
+
13
+ ## When to run it
14
+
15
+ You serve, or hunt customers for, a local trade: plumber, HVAC,
16
+ electrician, roofer, dentist, lawyer, any service people search for
17
+ when something just broke. Run the sweep when you need this week's
18
+ leads for one market, and run it again next week: the continuity step
19
+ is what makes the second run smarter than the first.
20
+
21
+ ## The five steps, in order
22
+
23
+ 1. **Open on the record.** Save the run's brief to memory under the
24
+ job id. If it is not written down, it did not happen.
25
+ 2. **capability_search** the landscape for the trade and city: what
26
+ services, angles, and offers exist before you spend a signal pull.
27
+ 3. **prompt_shield** the operator's targeting note. Notes steer the
28
+ run; screen them like any other input, especially pasted ones.
29
+ 4. **leadsignal** for the trade and city. This is the live pull: the
30
+ signals themselves, saved as the step's result.
31
+ 5. **continuity_get_recent** before you write a word of the brief.
32
+ What did this agent already find in this market? Chase what is new,
33
+ note what is repeat, never pitch the same lead twice by accident.
34
+
35
+ Then write the brief (signals first, landscape second, receipts last)
36
+ and **workflow_close** the job. The wrap binds only this run's
37
+ receipts. Work done outside the job cannot be wrapped into it later;
38
+ that refusal is the feature.
39
+
40
+ ## Rules that keep the run honest
41
+
42
+ - One caller handle per agent, saved at initialize, presented on every
43
+ call. Handles are identity; sharing one merges two agents into one
44
+ record.
45
+ - A receipt proves the saved result was not changed since the call
46
+ ran. It does not prove a lead is good. Say exactly that in the brief.
47
+ - Pickup is free forever: hand the wrapped job to another agent (or
48
+ your own other AI) and they continue from the record, not from a
49
+ summary.
50
+
51
+ ## Run it
52
+
53
+ pip install zambo-leadsignal
54
+ zambo-leadsignal run --trade plumber --city "Austin Texas"
55
+
56
+ npm install zambo-leadsignal
57
+ npx zambo-leadsignal run --trade plumber --city "Austin Texas"
58
+
59
+ Free tier: 20 calls and 1 wrap-up free every day per caller, picking
60
+ up in another AI always free. The Day Pass ($0.99) makes it unlimited
61
+ for 24 hours: https://zambo.dev/day-pass/
@@ -0,0 +1,10 @@
1
+ """zambo-leadsignal: run a lead signal sweep for a local trade market.
2
+
3
+ The pattern the live Zambo stream runs 200+ times a day, packaged:
4
+ search the capability landscape, shield the input, pull live lead
5
+ signals for a trade and city, check your own recent record so you do
6
+ not chase the same leads twice, write the brief, and wrap the run so
7
+ every step sits on a verifiable AER-1 receipt.
8
+ """
9
+
10
+ __version__ = "1.0.0"
@@ -0,0 +1,40 @@
1
+ """zambo-leadsignal command line.
2
+
3
+ zambo-leadsignal run --trade plumber --city "Austin Texas"
4
+ zambo-leadsignal run --trade roofer --city Denver --note "storm damage focus"
5
+
6
+ Configuration also by environment: ZAMBO_TRADE, ZAMBO_CITY,
7
+ ZAMBO_NOTE, ZAMBO_AGENT_ID, ZAMBO_MCP_URL.
8
+ """
9
+
10
+ import os
11
+ import sys
12
+
13
+ from .run import run_sweep
14
+
15
+
16
+ def _arg(flag, env, default=None):
17
+ if flag in sys.argv:
18
+ return sys.argv[sys.argv.index(flag) + 1]
19
+ return os.environ.get(env, default)
20
+
21
+
22
+ def main():
23
+ if len(sys.argv) < 2 or sys.argv[1] != "run":
24
+ print(__doc__)
25
+ return 2
26
+ trade = _arg("--trade", "ZAMBO_TRADE")
27
+ city = _arg("--city", "ZAMBO_CITY")
28
+ note = _arg("--note", "ZAMBO_NOTE")
29
+ if not trade or not city:
30
+ print("run needs --trade and --city (or ZAMBO_TRADE / ZAMBO_CITY)")
31
+ return 2
32
+ result = run_sweep(trade, city, note=note,
33
+ agent_id=os.environ.get("ZAMBO_AGENT_ID",
34
+ "leadsignal-agent"))
35
+ print(f"done: job {result['job_id']}")
36
+ return 0
37
+
38
+
39
+ if __name__ == "__main__":
40
+ raise SystemExit(main())
@@ -0,0 +1,193 @@
1
+ """Minimal Zambo MCP client: one agent identity, done right.
2
+
3
+ Step zero of the leadsignal pattern lives here. On initialize, the endpoint
4
+ issues a caller handle (in the initialize result's _meta and in the
5
+ X-Zambo-Caller-Handle response header). This client saves that handle
6
+ in the agent's own state file before anything else happens, and
7
+ presents it as _caller_handle on every call, with the agent's name as
8
+ _caller_label. Memory, job timelines, and the daily free allowance all
9
+ key to that handle. One handle per agent, never shared. Two agents on
10
+ one handle are one agent as far as the record is concerned.
11
+
12
+ Transport: requests when available (it handles proxies correctly),
13
+ standard library urllib otherwise. No other dependencies.
14
+ """
15
+
16
+ import json
17
+ import os
18
+ import re
19
+ import urllib.request
20
+ from pathlib import Path
21
+
22
+ try:
23
+ import requests
24
+
25
+ _HAS_REQUESTS = True
26
+ except ImportError: # pragma: no cover
27
+ _HAS_REQUESTS = False
28
+
29
+ MCP_URL = os.environ.get("ZAMBO_MCP_URL", "https://zambo.dev/mcp")
30
+ RUN_URL_RE = re.compile(r"https://zambo\.dev/run/[0-9a-f-]{36}")
31
+
32
+
33
+ def state_dir():
34
+ """Where this install keeps per-agent state files and contribution
35
+ notes. Defaults to ./.zambo-leadsignal in the working directory; override
36
+ with ZAMBO_LEADSIGNAL_STATE_DIR. State files hold caller handles: keep
37
+ them private, never commit them."""
38
+ return Path(os.environ.get("ZAMBO_LEADSIGNAL_STATE_DIR", Path.cwd() / ".zambo-leadsignal"))
39
+
40
+
41
+ class ZamboClient:
42
+ """One agent's session with the Zambo MCP endpoint."""
43
+
44
+ def __init__(self, agent_id, agent_name):
45
+ self.agent_id = agent_id
46
+ self.agent_name = agent_name
47
+ self.session_id = None
48
+ self.quota_handle = None
49
+ self._next_id = 0
50
+ self.state_file = state_dir() / f".zambo-state-{agent_id}.json"
51
+ self.caller_handle = self._load_saved_handle()
52
+
53
+ # -- identity persistence -------------------------------------------
54
+
55
+ def _load_saved_handle(self):
56
+ try:
57
+ data = json.loads(self.state_file.read_text())
58
+ return data.get("caller_handle")
59
+ except Exception:
60
+ return None
61
+
62
+ def _save_handle(self):
63
+ if self.caller_handle:
64
+ self.state_file.parent.mkdir(parents=True, exist_ok=True)
65
+ self.state_file.write_text(
66
+ json.dumps({"caller_handle": self.caller_handle}, indent=2)
67
+ )
68
+
69
+ # -- transport -------------------------------------------------------
70
+
71
+ def _post(self, payload, expect_response=True):
72
+ headers = {
73
+ "Content-Type": "application/json",
74
+ "Accept": "application/json, text/event-stream",
75
+ "X-Agent-Id": self.agent_id,
76
+ "X-Agent-Name": self.agent_name,
77
+ }
78
+ if self.session_id:
79
+ headers["Mcp-Session-Id"] = self.session_id
80
+
81
+ if _HAS_REQUESTS:
82
+ resp = requests.post(
83
+ MCP_URL, json=payload, headers=headers, timeout=60
84
+ )
85
+ resp.raise_for_status()
86
+ if self.session_id is None:
87
+ self.session_id = resp.headers.get("Mcp-Session-Id")
88
+ header_handle = resp.headers.get("X-Zambo-Caller-Handle")
89
+ raw = resp.text
90
+ else:
91
+ body = json.dumps(payload).encode()
92
+ req = urllib.request.Request(MCP_URL, data=body, headers=headers)
93
+ with urllib.request.urlopen(req, timeout=60) as resp:
94
+ if self.session_id is None:
95
+ self.session_id = resp.headers.get("Mcp-Session-Id")
96
+ header_handle = resp.headers.get("X-Zambo-Caller-Handle")
97
+ raw = resp.read().decode()
98
+
99
+ if header_handle and not self.caller_handle:
100
+ self.caller_handle = header_handle
101
+ if not expect_response:
102
+ return None
103
+ return self._parse_rpc(raw)
104
+
105
+ @staticmethod
106
+ def _parse_rpc(raw):
107
+ message = None
108
+ for line in raw.splitlines():
109
+ line = line.strip()
110
+ if line.startswith("data:"):
111
+ try:
112
+ message = json.loads(line[5:])
113
+ except Exception:
114
+ pass
115
+ if message is None:
116
+ message = json.loads(raw)
117
+ if "error" in message:
118
+ raise RuntimeError(f"MCP error: {message['error']}")
119
+ return message.get("result", {})
120
+
121
+ # -- MCP surface -----------------------------------------------------
122
+
123
+ def initialize(self):
124
+ result = self._post(
125
+ {
126
+ "jsonrpc": "2.0",
127
+ "id": self._id(),
128
+ "method": "initialize",
129
+ "params": {
130
+ "protocolVersion": "2025-03-26",
131
+ "capabilities": {},
132
+ "clientInfo": {"name": self.agent_name, "version": "1.0.0"},
133
+ },
134
+ }
135
+ )
136
+ meta = result.get("_meta", {})
137
+ if not self.caller_handle:
138
+ self.caller_handle = meta.get("caller_handle")
139
+ self.quota_handle = meta.get("quota_handle")
140
+ self._save_handle()
141
+ self._post(
142
+ {"jsonrpc": "2.0", "method": "notifications/initialized"},
143
+ expect_response=False,
144
+ )
145
+ return result
146
+
147
+ def call_tool(self, name, arguments):
148
+ # The caller handle rides in the arguments, the quota handle in
149
+ # _meta, and the agent's id as the caller label, so the shared
150
+ # job's record attributes every step to this agent.
151
+ args = dict(arguments)
152
+ if self.caller_handle:
153
+ args["_caller_handle"] = self.caller_handle
154
+ args.setdefault("_caller_label", self.agent_id)
155
+ params = {"name": name, "arguments": args}
156
+ if self.quota_handle:
157
+ params["_meta"] = {"quota_handle": self.quota_handle}
158
+ result = self._post(
159
+ {
160
+ "jsonrpc": "2.0",
161
+ "id": self._id(),
162
+ "method": "tools/call",
163
+ "params": params,
164
+ }
165
+ )
166
+ handle = (result.get("structuredContent") or {}).get("caller_handle")
167
+ if handle and not self.caller_handle:
168
+ self.caller_handle = handle
169
+ self._save_handle()
170
+ return result
171
+
172
+ def _id(self):
173
+ self._next_id += 1
174
+ return self._next_id
175
+
176
+
177
+ def receipt_link(result):
178
+ """Pull the AER-1 receipt link out of a tool result, if present."""
179
+ structured = result.get("structuredContent") or {}
180
+ for key in ("receipt_url", "run_url", "url"):
181
+ value = structured.get(key)
182
+ if isinstance(value, str) and "/run/" in value:
183
+ return value
184
+ match = RUN_URL_RE.search(json.dumps(result))
185
+ return match.group(0) if match else None
186
+
187
+
188
+ def result_text(result):
189
+ parts = []
190
+ for block in result.get("content") or []:
191
+ if block.get("type") == "text":
192
+ parts.append(block.get("text", ""))
193
+ return "\n".join(parts)
@@ -0,0 +1,89 @@
1
+ """The lead signal run: five receipted steps, one brief, one wrap.
2
+
3
+ capability_search what services and angles exist for this trade
4
+ prompt_shield screen the operator note before it steers work
5
+ leadsignal the live signals for (trade, city)
6
+ continuity_get_recent what this agent already found, so a repeat
7
+ run builds on the record instead of
8
+ starting from zero
9
+ workflow_close wrap the run; the wrap binds the job's own
10
+ receipts into one checkable record
11
+
12
+ Every call carries the run's job id as _session_id, so the wrap holds
13
+ exactly this run's steps and nothing else's.
14
+ """
15
+
16
+ import json
17
+ import re
18
+ import time
19
+ from pathlib import Path
20
+
21
+ from .client import ZamboClient, receipt_link, result_text
22
+
23
+
24
+ def slug(text):
25
+ return re.sub(r"[^a-z0-9]+", "-", text.lower()).strip("-")[:40]
26
+
27
+
28
+ def run_sweep(trade, city, note=None, agent_id="leadsignal-agent",
29
+ agent_name="Lead Signal Agent"):
30
+ stamp = time.strftime("%Y%m%d-%H%M%S", time.gmtime())
31
+ job_id = f"leadsignal-{slug(trade)}-{slug(city)}-{stamp}"
32
+ client = ZamboClient(agent_id, agent_name)
33
+ client.initialize()
34
+ receipts = {}
35
+
36
+ def step(tool, args):
37
+ result = client.call_tool(tool, {**args, "_session_id": job_id})
38
+ link = receipt_link(result)
39
+ receipts[tool] = link
40
+ print(f"[{tool}] receipt: {link}")
41
+ return result_text(result)
42
+
43
+ # Open the job on the record.
44
+ brief_fact = (
45
+ f"Lead signal run {job_id}: trade={trade}, city={city}. "
46
+ f"Operator note: {note or '(none)'}. Steps: capability_search, "
47
+ "prompt_shield, leadsignal, continuity_get_recent, wrap."
48
+ )
49
+ step("memory_remember", {"fact": brief_fact[:480],
50
+ "agent_name": agent_name})
51
+
52
+ landscape = step("capability_search",
53
+ {"q": f"{trade} services {city} lead generation"})
54
+ shield_input = note or f"Find new {trade} customers in {city} this week."
55
+ shield = step("prompt_shield", {"prompt": shield_input, "mode": "fast"})
56
+ signals = step("leadsignal", {"trade": trade, "city": city})
57
+ recent = step("continuity_get_recent", {"limit": 20})
58
+
59
+ brief = (
60
+ f"# Lead signal brief: {trade} in {city}\n\n"
61
+ f"Job: {job_id} (UTC {stamp})\n\n"
62
+ f"## Live signals (leadsignal)\n\n{signals}\n\n"
63
+ f"## Capability landscape (capability_search)\n\n{landscape}\n\n"
64
+ f"## Input screen (prompt_shield)\n\n{shield}\n\n"
65
+ f"## What this agent already had on record (continuity)\n\n"
66
+ f"{recent}\n\n"
67
+ f"## Receipts\n\n"
68
+ + "\n".join(f"- {t}: {u}" for t, u in receipts.items() if u)
69
+ + "\n\nEvery receipt recomputes at https://zambo.dev/verify/. "
70
+ "A receipt proves the saved result was not changed since the "
71
+ "call ran; it does not prove a lead is good. Work the signals, "
72
+ "and let the record keep you honest about what you already "
73
+ "chased.\n"
74
+ )
75
+ out = Path.cwd() / f"leadsignal-brief-{job_id}.md"
76
+ out.write_text(brief)
77
+ print(f"[brief] written: {out}")
78
+
79
+ wrap = client.call_tool(
80
+ "workflow_close",
81
+ {"_session_id": job_id,
82
+ "summary": f"Lead signal run for {trade} in {city}: live signals "
83
+ f"pulled, input screened, prior record checked, brief "
84
+ f"written to {out.name}."},
85
+ )
86
+ wrap_link = receipt_link(wrap)
87
+ print(f"[wrap] workflow_close receipt: {wrap_link}")
88
+ return {"job_id": job_id, "brief": str(out), "receipts": receipts,
89
+ "wrap_receipt": wrap_link}
@@ -0,0 +1,92 @@
1
+ Metadata-Version: 2.4
2
+ Name: zambo-leadsignal
3
+ Version: 1.0.0
4
+ Summary: Run a lead signal sweep for a local trade market on Zambo: live signals, screened input, continuity-checked, brief written, every step on a verifiable AER-1 receipt.
5
+ Author-email: Brennan Zambo <brennanzambo@zambo.dev>
6
+ License: MIT
7
+ Project-URL: Homepage, https://zambo.dev
8
+ Project-URL: Get started, https://zambo.dev/add/
9
+ Project-URL: Guide, https://rambozambodotdev.gitlab.io/aer1-hub/handover-graph.html
10
+ Project-URL: Repository, https://github.com/zambodotdev/zambo-leadsignal
11
+ Keywords: ai-agents,mcp,model-context-protocol,handover,receipts,zambo,aer-1
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Topic :: Software Development :: Libraries
17
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
18
+ Requires-Python: >=3.9
19
+ Description-Content-Type: text/markdown
20
+ Requires-Dist: requests>=2.28
21
+
22
+ # zambo-leadsignal
23
+
24
+ Run a lead signal sweep for a local trade market: live signals,
25
+ screened input, your own prior record checked before you write the
26
+ brief, and a verifiable AER-1 receipt for every step.
27
+
28
+ This is the most-run job shape on Zambo, packaged. In a five-day
29
+ first-hand count of the public receipt stream (16,221 receipts,
30
+ October 29 to November 2, 2026), the chain inside this package,
31
+ capability_search then prompt_shield then leadsignal then
32
+ continuity_get_recent then the write-up, appeared in roughly 200
33
+ caller-days per day. Agents were already running it by hand. Now it
34
+ installs.
35
+
36
+ ## Install
37
+
38
+ Python:
39
+
40
+ pip install zambo-leadsignal
41
+ zambo-leadsignal run --trade plumber --city "Austin Texas"
42
+
43
+ Node:
44
+
45
+ npm install zambo-leadsignal
46
+ npx zambo-leadsignal run --trade plumber --city "Austin Texas"
47
+
48
+ ## What a run does
49
+
50
+ 1. Opens the job on the record (memory_remember under the run's job id).
51
+ 2. capability_search: the service landscape for the trade and city.
52
+ 3. prompt_shield: screens the operator note before it steers the run.
53
+ 4. leadsignal: the live lead signals for that trade and city.
54
+ 5. continuity_get_recent: what this agent already found, so repeat
55
+ runs build on the record instead of starting from zero.
56
+ 6. Writes leadsignal-brief-<job>.md with the signals, the landscape,
57
+ the screen result, the prior record, and every receipt link.
58
+ 7. workflow_close: wraps the run. The wrap binds only this run's own
59
+ receipts, so the brief's proof layer is exactly the work that made
60
+ it.
61
+
62
+ Every receipt recomputes free at https://zambo.dev/verify/. A receipt
63
+ proves the saved result was not changed since the call ran; it does
64
+ not prove a lead is good. The brief says so, out loud, because that
65
+ honesty is the product.
66
+
67
+ ## Why Zambo is inside
68
+
69
+ The pattern runs on Zambo (https://zambo.dev/mcp), the verifiable
70
+ work layer for AI: 153 tools behind one MCP endpoint, memory and
71
+ continuity across AIs, and a verifiable AER-1 receipt for every job.
72
+ The package teaches the pattern by running it; Zambo is the mechanism
73
+ underneath: identity, memory, the signals tool, and the receipts.
74
+
75
+ Free tier: 20 calls and 1 wrap-up free every day, and picking up in
76
+ another AI is always free. Need more? The $0.99 Day Pass makes it
77
+ unlimited for 24 hours: https://zambo.dev/day-pass/
78
+
79
+ Add Zambo to your own AI in one URL, no key, no account:
80
+ https://zambo.dev/add/
81
+
82
+ ## Configuration
83
+
84
+ - ZAMBO_TRADE, ZAMBO_CITY, ZAMBO_NOTE: the run's inputs.
85
+ - ZAMBO_AGENT_ID: this agent's id (default: leadsignal-agent). One
86
+ identity per agent; the caller handle issued at initialize is saved
87
+ under ./.zambo-leadsignal and reused on later runs.
88
+ - ZAMBO_MCP_URL: endpoint override (default: https://zambo.dev/mcp).
89
+
90
+ ## License
91
+
92
+ MIT. Built by Brennan Zambo (brennanzambo@zambo.dev).
@@ -0,0 +1,13 @@
1
+ README.md
2
+ pyproject.toml
3
+ zambo_leadsignal/SKILL.md
4
+ zambo_leadsignal/__init__.py
5
+ zambo_leadsignal/cli.py
6
+ zambo_leadsignal/client.py
7
+ zambo_leadsignal/run.py
8
+ zambo_leadsignal.egg-info/PKG-INFO
9
+ zambo_leadsignal.egg-info/SOURCES.txt
10
+ zambo_leadsignal.egg-info/dependency_links.txt
11
+ zambo_leadsignal.egg-info/entry_points.txt
12
+ zambo_leadsignal.egg-info/requires.txt
13
+ zambo_leadsignal.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ zambo-leadsignal = zambo_leadsignal.cli:main
@@ -0,0 +1 @@
1
+ requests>=2.28
@@ -0,0 +1 @@
1
+ zambo_leadsignal