signalcore
The Python client for SignalCore: create agents, talk to them, and run everything around them (conversations, approvals, knowledge, records, apps) from your own code.
pip install signalcore
Python 3.11 or newer. Create an API key in the web app and export it:
export SIGNALCORE_API_KEY=sk_live_...
Quickstart
import asyncio
from signalcore import AsyncSignalcore
async def main() -> None:
async with AsyncSignalcore() as client: # reads SIGNALCORE_API_KEY
agent = await client.agents.create("Reception", instructions="You answer for Clínica Sol.")
await client.agents.publish(agent.id)
answer = await client.agents.invoke(
agent.id, input="Do you open on Saturdays?", thread="ticket-7"
)
print(answer.text)
async for event in client.runs.stream(answer.run_id): # the run's journal, live
print(event.event, event.json())
asyncio.run(main())
Code that does not use asyncio imports Signalcore instead: the same client, same names,
no await.
from signalcore import Signalcore
with Signalcore() as client:
for agent in client.agents.list().items:
print(agent.name)
What you get
- Every endpoint of the API, one attribute per family:
client.agents,client.runs,client.conversations,client.requests,client.documents,client.records,client.vault,client.connections,client.channels,client.skillsand the rest. Each method names the operation it calls. - Typed answers. Responses are pydantic models generated from
the API's contract (
signalcore.types), so your editor and type checker know every field. - Errors you can catch. Failures raise
NotFoundError,ForbiddenError,InvalidErrorand the like (allSignalcoreError), carrying the API'sstatus,code,detailand, for a body that did not fit, theerrorsfield by field. - Lists that page. Every list answers
itemsandnext_cursor. To read a whole list:client.iterate(client.conversations.list, status="open"). - Streams.
client.runs.stream(run_id)yields Server-Sent Events until the run isdoneorpaused; passlast_event_idto resume after a drop.client.build.sessions.say(...)streams a builder turn. - Several businesses. An agency's key acts as each of its clients:
client.for_org("org_...").agents.list(). - Live streams. What a run shows as it happens is watched from a browser, over a WebSocket.
client.live.url(stream_id)is its address (wss://<api>/v1/live/<id>?token=..., with this client's credential in the query): give it to@signalcore/ui'sLiveViewor the TypeScript client'slive.connect, only when the client holds an end user's token or a publishable key. It carries the credential, so never hand a browser one made with a secret key.
End users in the browser
The people who use your product can talk to your agents without your secret key ever reaching their browser. Your backend asks for a token for a person it knows and hands it over:
minted = await client.end_users.mint_token("user-42", name="Ana", email="ana@example.com")
# Hand minted.token to their browser: new Signalcore({ endUserToken }) in @signalcore/sdk,
# or AsyncSignalcore(end_user_token=...) from Python.
For visitors who are not signed in, make a publishable key that works only from your pages
(client.publishable_keys.create("Shop", ["https://shop.example.com"])) and give the client
publishable_key= with a visitor_id= the browser keeps. Both credentials can talk to live
agents and read their own runs, and nothing else; caller is who the credential says.
Your own components
What an agent can draw (cards, tables, forms) is a closed catalog, but your product has cards of its own. Register one by name, with the props it takes and a text for doors that cannot draw it, and agents can show it; your app draws it:
await client.ui.components.put(
"PropertyCard",
"Property card",
"A listing the customer asked about", # what the agent should use it for
{
"type": "object",
"properties": {"address": {"type": "string"}, "price": {"type": "number"}},
"required": ["address", "price"],
},
"{address}\nPrice: {price} EUR", # the text twin; {prop} is filled from the props
)
The schema is a small subset of JSON Schema: strings, numbers, whole numbers, booleans, lists of
those and one level of object; anything else is refused. An agent shows the component as a
Host node, {"id": "home", "component": "Host", "name": "PropertyCard", "props": {...}}
(sc.ui.host("PropertyCard", {...}) in agent code). Its props are checked against your schema
before anyone sees them, and the text twin is the surface's text when the agent wrote none.
client.ui.catalog() lists your components after the built-in ones.
Configuration
AsyncSignalcore(
api_key=None, # else SIGNALCORE_API_KEY
end_user_token=None, # instead of api_key: a person of your product, in their browser
publishable_key=None, # instead of api_key: a visitor, with visitor_id (8-128 characters)
visitor_id=None,
base_url=None, # else SIGNALCORE_BASE_URL, else https://signalcore.ai
org=None, # act as a business this key manages
timeout=30, # seconds
)
Pass exactly one of api_key, end_user_token and publishable_key.
Keys carry scopes (agents:read, runs:write...), so a key made for one job can do only
that job; a call outside its scopes raises ForbiddenError.
Documentation
Guides and the full API reference: https://signalcore.ai/docs.
MIT licensed.
Metadata
Release files for signalcore 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| signalcore-0.1.0.tar.gz | 34.0 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| signalcore-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 83.6 kB
Release files / signalcore-0.1.0.tar.gz
| Download URL | signalcore-0.1.0.tar.gz |
|---|---|
| Size | 34.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d1ef0e3901576839107316a8e39ee3c9d5cb159c128c46243aa6c12334ae8d92
|
|
BLAKE2b-256 checksum How to use checksums |
76188930f3845f0f1a31e3e073cdddc50ffc7f353c246b06acd9482d3f45875d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.
Transparency logRelease files / signalcore-0.1.0-py3-none-any.whl
| Download URL | signalcore-0.1.0-py3-none-any.whl |
|---|---|
| Size | 49.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
db1d5529c049b12f746aba252f990d493b85e89763fc2bd2f7069cd9c5d4b941
|
|
BLAKE2b-256 checksum How to use checksums |
6cd827ee94193a8bd49301d0ad6bd33497424dc25cb4eede8caae742b4dfb923
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.
Transparency logSecurity for signalcore 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for signalcore-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.