Skip to main content

Python bindings for Enki's Rust agent runtime.

Project description

enki-py

Python bindings for Enki's Rust agent runtime.

enki-py exposes two layers:

  • A high-level Python API built around Agent and MultiAgentRuntime
  • The lower-level native bindings generated from the Rust runtime, including workflow APIs

The package is designed for Python-first usage without giving up the native runtime features that already exist in the Rust core.

Requirements

  • Python >=3.8
  • A supported model string such as openai::gpt-4o, anthropic::claude-sonnet-4-6, or ollama::qwen3.5:latest

Install

Published package:

pip install enki-py

With the built-in LiteLLM adapter:

pip install "enki-py[litellm]"

Using uv:

uv add enki-py
uv add "enki-py[litellm]"

What It Exports

High-level Python API

The main Python-facing exports are:

  • Agent
  • AgentRunResult
  • ExecutionStep
  • Tool
  • RunContext
  • MemoryBackend
  • MemoryModule
  • MemoryEntry
  • MemoryKind
  • MultiAgentRuntime
  • MultiAgentMember
  • AgentCard
  • LiteLlmProvider
  • LlmProviderBackend

Low-level native bindings

The generated module is also re-exported, so lower-level runtime types remain available when you want to work closer to the Rust layer. Commonly used native types include:

  • EnkiAgent
  • EnkiWorkflowRuntime
  • EnkiTool and EnkiToolSpec
  • EnkiMemoryEntry
  • EnkiMemoryModule

Agent API

Agent is the main Python entrypoint. Its constructor supports:

  • model: required provider and model string
  • deps_type: optional dependency type used with RunContext
  • instructions: system guidance / prompt preamble
  • agentic_loop: optional custom loop instructions
  • name: display name for the agent
  • max_iterations: iteration cap for the runtime loop
  • workspace_home: optional workspace root for persisted runtime state
  • tools: optional list of pre-registered Tool objects
  • memories: optional list of MemoryModule objects
  • llm: optional Python-side LLM backend or callback

Main methods:

  • run(...): async single-agent execution
  • run_sync(...): sync wrapper around run(...)
  • tool_plain(...): decorator for plain Python tools
  • tool(...): decorator for tools that receive RunContext
  • register_tool(...)
  • register_memory(...)
  • as_workflow_agent(...): converts the wrapper into a workflow-configured low-level agent

The result of run(...) or run_sync(...) is AgentRunResult, which contains:

  • output: final model response text
  • steps: ExecutionStep entries describing runtime progress

Both run(...) and run_sync(...) accept:

  • session_id: optional explicit session id
  • deps: optional dependency object passed into RunContext
  • on_step: optional callback for streaming step visibility

Basic Agent

Synchronous example:

import uuid

from enki_py import Agent


agent = Agent(
    "anthropic::claude-sonnet-4-6",
    name="Simple Agent",
    instructions="Answer clearly and keep responses short.",
)

result = agent.run_sync(
    "Explain what this Enki Python example demonstrates.",
    session_id=f"simple-agent-{uuid.uuid4()}",
)

print(result.output)
for step in result.steps:
    print(f"{step.index}. [{step.phase}] {step.kind}: {step.detail}")

Async version:

import asyncio

from enki_py import Agent


async def main() -> None:
    agent = Agent(
        "ollama::qwen3.5:latest",
        name="Async Agent",
        instructions="Answer clearly and keep responses short.",
    )

    result = await agent.run("What does enki-py provide?")
    print(result.output)


asyncio.run(main())

Tools

The high-level wrapper lets you register Python functions directly as tools.

@agent.tool_plain

Use this when the tool only needs its declared arguments:

from enki_py import Agent


agent = Agent(
    "ollama::qwen3.5:latest",
    name="Researcher",
    instructions="Use tools when they help answer factual questions.",
)


@agent.tool_plain
def lookup_example_topics(topic: str) -> str:
    """Return a canned fact for an example topic."""
    facts = {
        "memory": "Memory lets the agent persist and recall useful session context.",
        "tools": "Tools let the agent call Python functions to fetch or compute structured results.",
        "multi-agent": "Multi-agent runtimes let a coordinator route work to specialized agents.",
    }
    return facts.get(topic.lower(), f"No prepared fact exists for '{topic}'.")

@agent.tool

Use this when the tool should receive a RunContext with typed dependencies:

from dataclasses import dataclass

from enki_py import Agent, RunContext


@dataclass
class AppDeps:
    project_name: str


agent = Agent(
    "ollama::qwen3.5:latest",
    deps_type=AppDeps,
    name="Context Agent",
    instructions="Use the provided context when it helps answer.",
)


@agent.tool
def project_name(ctx: RunContext[AppDeps]) -> str:
    """Return the active project name from runtime dependencies."""
    return ctx.deps.project_name

Tool schemas are inferred from Python signatures and type annotations. Required parameters come from arguments without defaults, and optional parameters come from arguments with defaults.

If you need lower-level control, you can also build Tool(...) values directly and register them with register_tool(...).

Memory

enki-py supports Python-defined memory modules through MemoryBackend and MemoryModule.

Implement MemoryBackend when you want custom record and recall behavior:

from dataclasses import dataclass, field
from time import time_ns

from enki_py import MemoryBackend, MemoryEntry, MemoryKind


@dataclass
class SessionMemory(MemoryBackend):
    name: str = "session_memory"
    _entries: dict[str, list[MemoryEntry]] = field(default_factory=dict)

    def record(self, session_id: str, user_msg: str, assistant_msg: str) -> None:
        entries = self._entries.setdefault(session_id, [])
        entries.append(
            MemoryEntry(
                key=f"{session_id}-{len(entries)}",
                content=f"User: {user_msg}\nAssistant: {assistant_msg}",
                kind=MemoryKind.RECENT_MESSAGE,
                relevance=1.0,
                timestamp_ns=time_ns(),
            )
        )

    def recall(self, session_id: str, query: str, max_entries: int) -> list[MemoryEntry]:
        entries = self._entries.get(session_id, [])
        return entries[-max_entries:]

    def flush(self, session_id: str) -> None:
        return None

Register it like this:

memory = SessionMemory()
agent = Agent(
    "ollama::qwen3.5:latest",
    memories=[memory.as_memory_module()],
)

Supported memory kinds:

  • MemoryKind.RECENT_MESSAGE
  • MemoryKind.SUMMARY
  • MemoryKind.ENTITY
  • MemoryKind.PREFERENCE

Memory callbacks may be synchronous or async def coroutines.

Multi-Agent Runtime

MultiAgentRuntime wires multiple Agent instances together and installs the coordination tools used for agent discovery and delegation.

Available methods:

  • registry()
  • discover(...)
  • process(...)
  • process_sync(...)

The runtime automatically installs two reserved tools on member agents:

  • discover_agents
  • delegate_task

Minimal example:

from enki_py import Agent, MultiAgentMember, MultiAgentRuntime


coordinator = Agent(
    "ollama::qwen3.5:latest",
    name="Coordinator",
    instructions=(
        "Use discover_agents first. "
        "Delegate research work to the researcher with delegate_task."
    ),
)

researcher = Agent(
    "ollama::qwen3.5:latest",
    name="Researcher",
    instructions="Answer delegated questions clearly and briefly.",
)

runtime = MultiAgentRuntime(
    [
        MultiAgentMember(
            agent_id="coordinator",
            agent=coordinator,
            capabilities=["planning", "orchestration"],
        ),
        MultiAgentMember(
            agent_id="researcher",
            agent=researcher,
            capabilities=["research"],
        ),
    ]
)

result = runtime.process_sync(
    "coordinator",
    "Use discover_agents first, then delegate to the researcher.",
    session_id="simple-multi-agent-example",
)

print(result.output)

Repository examples:

Workflow Runtime

For workflow execution, the lower-level EnkiWorkflowRuntime is the main entrypoint. A common pattern is:

  1. Create Python Agent wrappers
  2. Convert them with as_workflow_agent(agent_id=..., capabilities=[...])
  3. Provide JSON task definitions and JSON workflow definitions
  4. Start and inspect runs through the workflow runtime

Methods used in the checked-in Python examples include:

  • list_workflows_json()
  • list_runs_json()
  • inspect_json(run_id)
  • start_json(payload_json)
  • resume_json(run_id)
  • submit_intervention_json(run_id, intervention_id, response)

Workflow example:

import asyncio
import json
from pathlib import Path

import enki_py


WORKSPACE_HOME = Path("./example/enki-py/.enki-workflow")
MODEL = "ollama::qwen3.5:latest"


async def main() -> None:
    researcher = enki_py.Agent(
        MODEL,
        name="Researcher",
        instructions="Return short factual notes.",
        workspace_home=str(WORKSPACE_HOME),
    )
    writer = enki_py.Agent(
        MODEL,
        name="Writer",
        instructions="Turn notes into a concise summary.",
        workspace_home=str(WORKSPACE_HOME),
    )

    runtime = enki_py.EnkiWorkflowRuntime(
        agents=[
            researcher.as_workflow_agent(agent_id="researcher", capabilities=["research"]),
            writer.as_workflow_agent(agent_id="writer", capabilities=["writing"]),
        ],
        tasks_json=[],
        workflows_json=[],
        workspace_home=str(WORKSPACE_HOME),
    )

    print(json.loads(await runtime.list_workflows_json()))


asyncio.run(main())

For a complete runnable version with task and edge definitions, see example/enki-py/agent_workflow.py.

Human Intervention

Workflow runs can pause for human input and then resume from persisted state.

Two built-in patterns are demonstrated in the repository examples:

  • human_gate workflow nodes that pause and wait for a human response
  • task nodes with failure_policy: "pause_for_intervention" that convert a failure into a human resolution step

The runtime interaction loop is:

  1. start_json(...) starts the workflow and may return a paused response
  2. inspect_json(run_id) exposes pending_interventions
  3. submit_intervention_json(run_id, intervention_id, response) resolves the intervention
  4. resume_json(run_id) continues the persisted run

See example/enki-py/human_intervention_workflow.py.

Custom LLM Providers

You can keep model execution on the Python side by passing either:

  • an instance of LlmProviderBackend
  • a compatible Python callable matching the LLM completion shape

The built-in LiteLlmProvider is the default adapter for LiteLLM-backed usage. It is useful when you want:

  • provider-specific configuration in Python
  • LiteLLM-managed credentials or routing
  • a Python extension point without changing Rust code

Notes from the current implementation:

  • LiteLlmProvider raises a clear error if litellm is not installed
  • for Ollama, the default base URL comes from OLLAMA_URL or falls back to http://127.0.0.1:11434
  • ENKI_LITELLM_TIMEOUT controls the request timeout used by the adapter
  • Ollama tool calling is only forwarded when ENKI_OLLAMA_TOOLS is truthy

The repository workflow example also includes a custom OllamaProvider implementation in example/enki-py/agent_workflow.py.

Custom Agentic Loop

You can override the default loop instructions with agentic_loop=:

from enki_py import Agent


agent = Agent(
    "anthropic::claude-sonnet-4-6",
    name="Custom Agentic Loop",
    instructions="Answer clearly and keep responses short.",
    agentic_loop=(
        "1. Understand the user request.\n"
        "2. Decide whether a tool is necessary before acting.\n"
        "3. If you use a tool, summarize what you learned.\n"
        "4. Verify that the answer is complete.\n"
        "5. Return the final response."
    ),
)

See example/enki-py/custom_agentic_loop.py.

Running The Examples

After building the local package with maturin develop, you can run the checked-in examples from the repository root:

python example\enki-py\simple_agent.py
python example\enki-py\simple_agent_ollama.py
python example\enki-py\simple_multi_agent.py
python example\enki-py\multi_agent_with_memory_and_tools.py
python example\enki-py\agent_workflow.py
python example\enki-py\human_intervention_workflow.py

Model notes:

  • simple_agent.py uses anthropic::claude-sonnet-4-6
  • simple_agent_ollama.py uses ollama::qwen3.5
  • several other checked-in examples use ollama::qwen3.5:latest
  • agent_workflow.py reads ENKI_MODEL and falls back to ollama::qwen3.5:latest

Make sure the selected provider and model are available in your local environment before running the examples.

Development

From crates/bindings/enki-py:

pip install maturin
maturin develop
pytest python/tests

Useful commands:

  • maturin develop: build the Rust extension and install the package in editable form
  • pytest python/tests: run the Python-side tests and examples under test coverage

Project Layout

crates/bindings/enki-py/
|-- Cargo.toml
|-- pyproject.toml
|-- python/enki_py/
|-- python/tests/
`-- src/
  • src/: Rust UniFFI binding implementation
  • python/enki_py/: Python wrapper and generated native module
  • python/tests/: Python-side tests and usage coverage

Related Docs

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

enki_py-0.5.31.tar.gz (418.6 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

enki_py-0.5.31-py3-none-win_arm64.whl (1.4 MB view details)

Uploaded Python 3Windows ARM64

enki_py-0.5.31-py3-none-win_amd64.whl (1.5 MB view details)

Uploaded Python 3Windows x86-64

enki_py-0.5.31-py3-none-win32.whl (1.3 MB view details)

Uploaded Python 3Windows x86

enki_py-0.5.31-py3-none-musllinux_1_2_x86_64.whl (1.7 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

enki_py-0.5.31-py3-none-musllinux_1_2_i686.whl (1.7 MB view details)

Uploaded Python 3musllinux: musl 1.2+ i686

enki_py-0.5.31-py3-none-musllinux_1_2_armv7l.whl (1.6 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARMv7l

enki_py-0.5.31-py3-none-musllinux_1_2_aarch64.whl (1.5 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

enki_py-0.5.31-py3-none-manylinux_2_28_x86_64.whl (1.5 MB view details)

Uploaded Python 3manylinux: glibc 2.28+ x86-64

enki_py-0.5.31-py3-none-manylinux_2_28_s390x.whl (1.6 MB view details)

Uploaded Python 3manylinux: glibc 2.28+ s390x

enki_py-0.5.31-py3-none-manylinux_2_28_ppc64le.whl (1.5 MB view details)

Uploaded Python 3manylinux: glibc 2.28+ ppc64le

enki_py-0.5.31-py3-none-manylinux_2_28_i686.whl (1.5 MB view details)

Uploaded Python 3manylinux: glibc 2.28+ i686

enki_py-0.5.31-py3-none-manylinux_2_28_armv7l.whl (1.4 MB view details)

Uploaded Python 3manylinux: glibc 2.28+ ARMv7l

enki_py-0.5.31-py3-none-manylinux_2_28_aarch64.whl (1.4 MB view details)

Uploaded Python 3manylinux: glibc 2.28+ ARM64

enki_py-0.5.31-py3-none-macosx_11_0_arm64.whl (1.3 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

enki_py-0.5.31-py3-none-macosx_10_12_x86_64.whl (1.4 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file enki_py-0.5.31.tar.gz.

File metadata

  • Download URL: enki_py-0.5.31.tar.gz
  • Upload date:
  • Size: 418.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for enki_py-0.5.31.tar.gz
Algorithm Hash digest
SHA256 6fb6621867fa85ed248795ee8568d66e8e2872525a29253b343fb677816f0fbe
MD5 de873d6d8b8380ee62128e0d308a305f
BLAKE2b-256 4b18728a31f158ac4de2b8d1e04dd80a84fead975c0560bbd9096e02ac726b0e

See more details on using hashes here.

File details

Details for the file enki_py-0.5.31-py3-none-win_arm64.whl.

File metadata

  • Download URL: enki_py-0.5.31-py3-none-win_arm64.whl
  • Upload date:
  • Size: 1.4 MB
  • Tags: Python 3, Windows ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for enki_py-0.5.31-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 5e6a70c5ba3cf7c250a762ccaa299f4d9c4c156f25c49343757d63607f04cfd3
MD5 295627957f5a016fd668f357e1821066
BLAKE2b-256 5d25e0645e0fb076f453bcb11dd3b21b8158f2b411a2da8df454b3812e7d73ee

See more details on using hashes here.

File details

Details for the file enki_py-0.5.31-py3-none-win_amd64.whl.

File metadata

  • Download URL: enki_py-0.5.31-py3-none-win_amd64.whl
  • Upload date:
  • Size: 1.5 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for enki_py-0.5.31-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 7e2f62d2fbc480248f11bd95e8bb298cb155ce8e8e070f88d97354e2fdfc4657
MD5 64fd98bf953a6ed864d6dd62f802deae
BLAKE2b-256 369354e3ab9b88c33d8e74be9b34f81b4277480a1bd43e6fcd9e0ea55b584d00

See more details on using hashes here.

File details

Details for the file enki_py-0.5.31-py3-none-win32.whl.

File metadata

  • Download URL: enki_py-0.5.31-py3-none-win32.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: Python 3, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for enki_py-0.5.31-py3-none-win32.whl
Algorithm Hash digest
SHA256 32f198e0fb7ec0175f2ed6bca4f8a4b67969fcb65ba0824edf563346fab4e320
MD5 ca2dc7fb4565ecf95af42351e0c35778
BLAKE2b-256 c786fb1ac22da8b1c8b3eeb0c419cfa1e4b897d9ced7b22bbb50fa7a7d45f3c7

See more details on using hashes here.

File details

Details for the file enki_py-0.5.31-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for enki_py-0.5.31-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 47ff0e2c2155368eccd79278e4bda49844462433ab8f8e93eb2bd275e30ed5e4
MD5 7fedb219a6034f1f8e2b3aa659457dcb
BLAKE2b-256 47a24198269619c164696700dde4537d7ceaef3bfcf09348d4f6004402432424

See more details on using hashes here.

File details

Details for the file enki_py-0.5.31-py3-none-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for enki_py-0.5.31-py3-none-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 a00ee93e242510d3689fee0c47eeb5864b8f454f7a41246a1ce5177e6867d835
MD5 290ccee99960d09f2d5519b9644a5b7e
BLAKE2b-256 91411ab3fc34dc379c08ecc8c1760950b0d8f42233d55f8b1458b63166393b9d

See more details on using hashes here.

File details

Details for the file enki_py-0.5.31-py3-none-musllinux_1_2_armv7l.whl.

File metadata

File hashes

Hashes for enki_py-0.5.31-py3-none-musllinux_1_2_armv7l.whl
Algorithm Hash digest
SHA256 0b595379d2ccb07730674b050c54e8782711a5b0ff4fd11471bc1eea372d5567
MD5 f1fa045bdee6f61045a707fbaf086ed6
BLAKE2b-256 9dff0dce2b77bd722b496fce455c85fbbc3a72eda59bb2272c740121d8b8e1e4

See more details on using hashes here.

File details

Details for the file enki_py-0.5.31-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for enki_py-0.5.31-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 4387d9d9313ea0b2170fcf99f5925d2192132092c1acf01e21d523a3cb003dfd
MD5 415cb55293a53e792c71019456a8ce17
BLAKE2b-256 14f88eff99bee5d1f136237ebeba20ff59c42badaadbe1cb6e588f2185b1581f

See more details on using hashes here.

File details

Details for the file enki_py-0.5.31-py3-none-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for enki_py-0.5.31-py3-none-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 4b094450a52b91d4a2892f430e9c80bcf2bf79df1364a8b1aa2b309813b2ef9d
MD5 bdf42b8173a22d26a07359da993a008f
BLAKE2b-256 30a32469e4708e8f026171dcf8ca3de5654e4c80342cbee87e7ab1cc668d009d

See more details on using hashes here.

File details

Details for the file enki_py-0.5.31-py3-none-manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for enki_py-0.5.31-py3-none-manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 798db4aaba1d785d49f6db712449f22a2f0523933f3b92c7b0d854c3f3ef18b4
MD5 32806e9db335cc41a155c1f3c518996d
BLAKE2b-256 8e99c49418637659a125f4c1abae927ca6c4ade58430f30200ee3746b3108841

See more details on using hashes here.

File details

Details for the file enki_py-0.5.31-py3-none-manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for enki_py-0.5.31-py3-none-manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 767426d090df43b5e47e2538bfcfbc159485c20614d2b0a930e83129d0731e30
MD5 7004b1ab912af4ebf5d1a6948a9d2ece
BLAKE2b-256 fbdd059b7c52215116d4a605bc684e35dccbc30e1d9d65c1ed73d5e6497df98d

See more details on using hashes here.

File details

Details for the file enki_py-0.5.31-py3-none-manylinux_2_28_i686.whl.

File metadata

File hashes

Hashes for enki_py-0.5.31-py3-none-manylinux_2_28_i686.whl
Algorithm Hash digest
SHA256 fe75bc12741db23899724a074fe7209a69f0cda3f5fb9bb870a275933078e1fa
MD5 94fcd3eb77c3f556a274a8d743f8bdbb
BLAKE2b-256 4878b20043b8f6f0c5e90e96dc7b4f36a79f621a08a32644f44380ac41eb8af4

See more details on using hashes here.

File details

Details for the file enki_py-0.5.31-py3-none-manylinux_2_28_armv7l.whl.

File metadata

File hashes

Hashes for enki_py-0.5.31-py3-none-manylinux_2_28_armv7l.whl
Algorithm Hash digest
SHA256 6c6c358613d0c62bfbd0fc5ab8acdc3b26bd99989967705d94255e9adaf06626
MD5 259617ad5a45cd957f07a2afee26f9a2
BLAKE2b-256 f5df1eb89d1875b95fe0f5dc87f15e8eacd45943a67e2f34094f28f0f60907d9

See more details on using hashes here.

File details

Details for the file enki_py-0.5.31-py3-none-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for enki_py-0.5.31-py3-none-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 cf5f59f37674d5e34bb12d2fea6d7c4b4070cd514fcc2ad0a21fbb5738771c6e
MD5 c4fa2eda4943d67611b72036287f9776
BLAKE2b-256 99689cd382527a8fc10551d4ebf01494d09c9cd35adb4fdc494faae1a730850e

See more details on using hashes here.

File details

Details for the file enki_py-0.5.31-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for enki_py-0.5.31-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a9ee926e4bc8873d7fd6527f7387bc3c20d4acb272258e6de6940f878cd678b1
MD5 41dfced73a7d784177ffd7c5d94a412c
BLAKE2b-256 5b7e1a587b9238da48e8dcf34721deb22b2131db5dc0fce32f097a7df46a0492

See more details on using hashes here.

File details

Details for the file enki_py-0.5.31-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for enki_py-0.5.31-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 ccc3d0f6d7c267f3ed0706cd5c2fd6d36f3ea4bd1d66059878a75713a211268b
MD5 1b904bd4289d9cbb5ade39136d5955e9
BLAKE2b-256 16b7f09babf7f589d042eef430d9940eb9bee5e1ad96c688f8020eb1ba2a5559

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page