{"id":16559542,"url":"https://github.com/dvf/synapse","last_synced_at":"2026-05-19T12:01:21.634Z","repository":{"id":57425996,"uuid":"143869243","full_name":"dvf/synapse","owner":"dvf","description":"Rapid RPC framework for building Python services fast","archived":false,"fork":false,"pushed_at":"2019-05-25T22:40:20.000Z","size":74,"stargazers_count":14,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-11-28T02:03:16.519Z","etag":null,"topics":["asyncio","flask","framework","msgpack","python","python3"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dvf.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-08-07T12:20:33.000Z","updated_at":"2025-05-31T17:19:20.000Z","dependencies_parsed_at":"2022-09-19T06:01:09.515Z","dependency_job_id":null,"html_url":"https://github.com/dvf/synapse","commit_stats":null,"previous_names":["dvf/electron"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/dvf/synapse","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvf%2Fsynapse","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvf%2Fsynapse/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvf%2Fsynapse/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvf%2Fsynapse/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dvf","download_url":"https://codeload.github.com/dvf/synapse/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvf%2Fsynapse/sbom","scorecard":{"id":360806,"data":{"date":"2025-08-11","repo":{"name":"github.com/dvf/synapse","commit":"909158975887bd4d94d96f41a934af18b3925f50"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.8,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/27 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":4,"reason":"6 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: PYSEC-2022-14 / GHSA-39ph-wr67-j4xq","Warn: Project is vulnerable to: PYSEC-2020-92 / GHSA-hj5v-574p-mj7c","Warn: Project is vulnerable to: PYSEC-2022-42969","Warn: Project is vulnerable to: PYSEC-2021-140 / GHSA-9w8r-397f-prfh","Warn: Project is vulnerable to: PYSEC-2023-117 / GHSA-mrwq-x4v8-fh7p","Warn: Project is vulnerable to: PYSEC-2021-141 / GHSA-pq64-v7f5-gqh8"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 5 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T10:48:23.161Z","repository_id":57425996,"created_at":"2025-08-18T10:48:23.161Z","updated_at":"2025-08-18T10:48:23.161Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33215443,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-19T07:54:09.561Z","status":"ssl_error","status_checked_at":"2026-05-19T07:54:08.508Z","response_time":58,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asyncio","flask","framework","msgpack","python","python3"],"created_at":"2024-10-11T20:26:17.924Z","updated_at":"2026-05-19T12:01:21.627Z","avatar_url":"https://github.com/dvf.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cpicture\u003e\n\u003cimg width=\"974\" height=\"513\" alt=\"image\" src=\"https://github.com/user-attachments/assets/1f54fbb5-731c-470a-aaca-5f947c420d8b\" /\u003e\n\u003c/picture\u003e\n\n# Synapse P2P\n\n**A network substrate for Python agents.**\n\nSynapse P2P is a tiny async RPC, discovery, and capability-publishing layer for building agent-to-agent networks, local agent swarms, distributed tools, peer-to-peer services, and lightweight service meshes.\n\nIt is designed to be useful to both humans and LLM agents:\n\n- Humans get a simple Python API.\n- Agents get discoverable methods, published capabilities, structured request/response messages, and machine-readable metadata.\n\n```python\n@app.endpoint(\"sum\")\nasync def sum_endpoint(a: int, b: int) -\u003e int:\n    return a + b\n```\n\n```python\nresult = await Client(\"127.0.0.1\", 9999).call(\"sum\", 1, 2)\n```\n\n## Why Synapse?\n\nLLM agents need a way to find each other, ask what each other can do, and delegate work over a small, predictable protocol.\n\nSynapse provides the substrate for that:\n\n- **RPC**: call remote Python functions over TCP.\n- **Discovery**: inspect published methods and agent capabilities.\n- **Agent identity**: expose role, description, and capabilities.\n- **Delegation**: send tasks to another agent through `_agent.ask`.\n- **Structured protocol**: MsgPack request/response envelopes with request IDs and errors.\n\nThink of it as a minimal network layer for agentic systems — not a framework that decides how agents think, but a substrate they can use to connect.\n\n## Features\n\n- **Async TCP RPC** built on `asyncio`\n- **MsgPack serialization** for compact binary messages\n- **Length-prefixed framing** for reliable message boundaries over TCP\n- **Decorator-based endpoints** with `@app.endpoint(...)`\n- **Built-in async client** with request/response handling\n- **Structured responses and errors** via `RPCResponse` and `RPCError`\n- **Positional and keyword arguments** for remote calls\n- **Request IDs** for correlation and future persistent-connection support\n- **Published method discovery** via `_synapse.methods`\n- **Agent metadata discovery** via `_agent.info` and `_agent.capabilities`\n- **Agent task delegation** via `_agent.ask`\n- **Periodic background tasks** with `@app.background(...)`\n- **Serializer abstraction** for custom protocols later\n- **P2P-oriented primitives** such as node identity and XOR-distance helpers\n\n## Installation\n\n```bash\npip install synapse-p2p\n```\n\nFor development with [uv](https://docs.astral.sh/uv/):\n\n```bash\nuv sync --group dev\nuv run pytest\nuv run ruff check .\nuv run pyrefly check\n```\n\n## Quickstart: RPC server and client\n\nCreate a server:\n\n```python\nfrom synapse_p2p import Server\n\napp = Server(address=\"127.0.0.1\", port=9999)  # or Server() for defaults\n\n\n@app.endpoint(\"sum\", description=\"Add two numbers\")\nasync def sum_endpoint(a: int, b: int) -\u003e int:\n    \"\"\"Add two numbers.\"\"\"\n    return a + b\n\n\nif __name__ == \"__main__\":\n    app.run()\n```\n\nCall it from a client:\n\n```python\nimport asyncio\n\nfrom synapse_p2p import Client\n\n\nasync def main() -\u003e None:\n    client = Client(\"127.0.0.1\", 9999)\n    result = await client.call(\"sum\", 1, 2)\n    print(result)\n\n\nasyncio.run(main())\n```\n\nOutput:\n\n```text\n3\n```\n\n## Quickstart: agent node\n\nAn `AgentNode` is a Synapse server that publishes agent metadata and accepts delegated work.\n\n```python\nfrom synapse_p2p import AgentNode\n\nagent = AgentNode(\n    name=\"Reviewer\",\n    role=\"reviewer\",\n    description=\"Reviews Python code and suggests tests.\",\n    capabilities=[\"python\", \"code-review\", \"pytest\"],\n)\n\n\n@agent.task_handler\nasync def handle_task(task: str, context: dict):\n    return {\n        \"status\": \"done\",\n        \"result\": f\"Reviewed task: {task}\",\n        \"context_keys\": list(context),\n    }\n\n\nagent.run()\n```\n\nAnother agent or client can inspect it:\n\n```python\ninfo = await client.call(\"_agent.info\")\ncapabilities = await client.call(\"_agent.capabilities\")\n```\n\nAnd delegate work:\n\n```python\nresult = await client.call(\n    \"_agent.ask\",\n    \"Review this pull request\",\n    context={\"files\": [\"server.py\", \"client.py\"]},\n)\n```\n\n## Built-in discovery endpoints\n\nSynapse reserves `_synapse.*` for substrate-level metadata.\n\n### `_synapse.ping`\n\nHealth check:\n\n```python\nawait client.call(\"_synapse.ping\")\n# \"pong\"\n```\n\n### `_synapse.methods`\n\nReturns published RPC methods:\n\n```python\nmethods = await client.call(\"_synapse.methods\")\nprint(methods)\n```\n\nFor this endpoint:\n\n```python\n@app.endpoint(\"sum\")\nasync def sum_endpoint(a: int, b: int) -\u003e int:\n    \"\"\"Add two numbers.\"\"\"\n    return a + b\n```\n\nThe result is:\n\n```python\n[\n    {\n        \"name\": \"sum\",\n        \"publish\": True,\n        \"description\": \"Add two numbers.\",\n    }\n]\n```\n\nEndpoints are published by default. Add a docstring to make them more useful to humans and agents inspecting `_synapse.methods`:\n\n```python\n@app.endpoint(\"image.resize\")\nasync def resize_image(...):\n    \"\"\"Resize an image.\"\"\"\n    ...\n```\n\nPrivate endpoints can opt out:\n\n```python\n@app.endpoint(\"admin.restart\", publish=False)\nasync def restart():\n    ...\n```\n\n## Built-in agent endpoints\n\nSynapse reserves `_agent.*` for agent-level metadata and task delegation.\n\n### `_agent.info`\n\nReturns agent identity:\n\n```python\n{\n    \"name\": \"Reviewer\",\n    \"role\": \"reviewer\",\n    \"description\": \"Reviews Python code and suggests tests.\",\n    \"capabilities\": [\"python\", \"code-review\", \"pytest\"],\n}\n```\n\n### `_agent.capabilities`\n\nReturns machine-readable capability descriptors:\n\n```python\n[\n    {\n        \"name\": \"code-review\",\n        \"description\": \"Review Python code for correctness and maintainability.\",\n        \"input_schema\": {},\n        \"output_schema\": {},\n    }\n]\n```\n\nCapabilities can be strings or explicit descriptors:\n\n```python\nfrom synapse_p2p import AgentCapability, AgentNode\n\nagent = AgentNode(\n    name=\"Researcher\",\n    role=\"researcher\",\n    capabilities=[\n        AgentCapability(\n            name=\"web-research\",\n            description=\"Find and summarize evidence from the web.\",\n            input_schema={\"query\": \"string\"},\n            output_schema={\"summary\": \"string\", \"sources\": \"array\"},\n        )\n    ],\n)\n```\n\n### `_agent.ask`\n\nDelegates a task to the agent's registered task handler:\n\n```python\nawait client.call(\n    \"_agent.ask\",\n    \"Find bugs in this module\",\n    context={\"code\": \"...\"},\n)\n```\n\nThe task handler receives:\n\n```python\nasync def handle_task(task: str, context: dict):\n    ...\n```\n\n## Patterns for LLM agents\n\n### 1. Discover a peer\n\n```python\ninfo = await client.call(\"_agent.info\")\nmethods = await client.call(\"_synapse.methods\")\ncapabilities = await client.call(\"_agent.capabilities\")\n```\n\n### 2. Select a peer by capability\n\n```python\nif \"code-review\" in info[\"capabilities\"]:\n    result = await client.call(\"_agent.ask\", \"Review this diff\", context={\"diff\": diff})\n```\n\n### 3. Publish tools as RPC methods\n\n```python\n@app.endpoint(\"filesystem.search\")\nasync def search_files(pattern: str) -\u003e list[str]:\n    \"\"\"Search files by regex.\"\"\"\n    ...\n```\n\n### 4. Hide dangerous tools\n\n```python\n@app.endpoint(\"shell.exec\", publish=False)\nasync def shell_exec(command: str) -\u003e str:\n    ...\n```\n\nPrivate methods are still callable if known, but they are not advertised by `_synapse.methods`.\n\n## Server lifecycle\n\nUse `app.run()` for simple scripts. In larger async applications or tests, use `start()` and `stop()`:\n\n```python\nserver = await app.start()\ntry:\n    ...\nfinally:\n    await app.stop()\n```\n\n## Background tasks\n\nSynapse can run recurring async background jobs alongside your RPC server:\n\n```python\nfrom synapse_p2p import Server\n\napp = Server()\n\n\n@app.background(5)\nasync def heartbeat():\n    print(\"heartbeat: server is still alive\")\n\n\n@app.endpoint(\"sum\")\nasync def sum_endpoint(a: int, b: int) -\u003e int:\n    return a + b\n\n\nif __name__ == \"__main__\":\n    app.run()\n```\n\nStartup output will include the task:\n\n```text\nBackground Tasks:\n- heartbeat (5s)\n```\n\nThe task above runs roughly every five seconds. Exceptions are logged and do not stop future runs.\n\n## Structured protocol\n\nSynapse sends length-prefixed MsgPack messages over TCP.\n\nA request looks like:\n\n```python\nRPCRequest(\n    id=\"request-id\",\n    endpoint=\"sum\",\n    args=[1, 2],\n    kwargs={},\n)\n```\n\nA successful response looks like:\n\n```python\nRPCResponse(\n    id=\"request-id\",\n    ok=True,\n    result=3,\n)\n```\n\nAn error response looks like:\n\n```python\nRPCResponse(\n    id=\"request-id\",\n    ok=False,\n    error=RPCError(code=\"bad_request\", message=\"Unregistered endpoint called: nope\"),\n)\n```\n\n## Low-level access\n\nMost users should use `Client`, but lower-level message types are exported if you want to build custom transports or tooling:\n\n```python\nfrom synapse_p2p import RPCError, RPCRequest, RPCResponse, RemoteProcedureCall\nfrom synapse_p2p.framing import read_frame, write_frame\nfrom synapse_p2p.serializers import MessagePackRPCSerializer\n```\n\n`RemoteProcedureCall` is kept as a backwards-compatible alias for `RPCRequest`.\n\n## Project status\n\nSynapse is intentionally small and evolving. The current focus is a clean async RPC and agent substrate. Future work may include:\n\n- Peer discovery and bootstrap peer exchange\n- Agent-to-agent network discovery\n- Long-running jobs for agent tasks\n- Persistent connections and streaming events\n- Routing tables / Kademlia-style node lookup\n- Handshakes and node capabilities\n- Authenticated or encrypted messages\n- Broadcast and gossip primitives\n\n## Keywords\n\nPython agent substrate, agent-to-agent networking, LLM agent RPC, multi-agent systems, agent discovery, capability discovery, Python RPC, asyncio RPC, peer-to-peer Python, P2P networking, MsgPack RPC, TCP RPC, async microservices, distributed agents, distributed workers, service-to-service communication.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdvf%2Fsynapse","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdvf%2Fsynapse","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdvf%2Fsynapse/lists"}