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.5.tar.gz (421.5 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.5-py3-none-win_arm64.whl (1.5 MB view details)

Uploaded Python 3Windows ARM64

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

Uploaded Python 3Windows x86-64

enki_py-0.5.5-py3-none-win32.whl (1.4 MB view details)

Uploaded Python 3Windows x86

enki_py-0.5.5-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.5-py3-none-musllinux_1_2_i686.whl (1.7 MB view details)

Uploaded Python 3musllinux: musl 1.2+ i686

enki_py-0.5.5-py3-none-musllinux_1_2_armv7l.whl (1.7 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARMv7l

enki_py-0.5.5-py3-none-musllinux_1_2_aarch64.whl (1.6 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

enki_py-0.5.5-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.5-py3-none-manylinux_2_28_s390x.whl (1.6 MB view details)

Uploaded Python 3manylinux: glibc 2.28+ s390x

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

Uploaded Python 3manylinux: glibc 2.28+ ppc64le

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

Uploaded Python 3manylinux: glibc 2.28+ i686

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

Uploaded Python 3manylinux: glibc 2.28+ ARMv7l

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

Uploaded Python 3manylinux: glibc 2.28+ ARM64

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

Uploaded Python 3macOS 11.0+ ARM64

enki_py-0.5.5-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.5.tar.gz.

File metadata

  • Download URL: enki_py-0.5.5.tar.gz
  • Upload date:
  • Size: 421.5 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.5.tar.gz
Algorithm Hash digest
SHA256 caa899c429ab11004ccf307987e7564fda26ed151f76e3b8b7eb53ccd48ed263
MD5 6d555dcded1a0a3920c66b30a3abbe39
BLAKE2b-256 2fa7b685309bc858c45245bfea1cd477a6c983347a6dac35847bf1cab3289e07

See more details on using hashes here.

File details

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

File metadata

  • Download URL: enki_py-0.5.5-py3-none-win_arm64.whl
  • Upload date:
  • Size: 1.5 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.5-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 a8648f290edc82f525bc53535cdc6eed8c0887baf70db2513bb21321055b1e69
MD5 e25ead6603fa4a67e1b89fdd92b56c59
BLAKE2b-256 3f4056c17b1dfecada816d47494c7f0721c6c47b457b0727772c4ec6597573d0

See more details on using hashes here.

File details

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

File metadata

  • Download URL: enki_py-0.5.5-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.5-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 f7fab6670e732aa0a7af876082a99fb4be524b74de09ddfc38cebdba474e12dd
MD5 6002acf303d14241cad1af4f6afe5bcd
BLAKE2b-256 401db65cec2e9243e44ae2854223ca1245a3f5c73abba65b148c71e8bdcce2b3

See more details on using hashes here.

File details

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

File metadata

  • Download URL: enki_py-0.5.5-py3-none-win32.whl
  • Upload date:
  • Size: 1.4 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.5-py3-none-win32.whl
Algorithm Hash digest
SHA256 e339b530f62845be1ed058ecc56c3050f0eea0d0c7f0c10c2ec779d230b2f2f1
MD5 f112bf436eeef5262ffacdb74a6d82a8
BLAKE2b-256 e90b7877c7a49f11eb54e39ec035b1c7ca5c2f1997ccc8687620bd6900644451

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for enki_py-0.5.5-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 a0bfb5cfb3742ad8f7074ddadd27021aabed9cd661b79e9c163aafb7243a8eee
MD5 b071772ce021916947080d70184d257e
BLAKE2b-256 42da1b9cbaeeeb874dfe89efda5b10662b2e665e659af6cac2cdc73a50ddeedc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for enki_py-0.5.5-py3-none-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 2d388cdfa94b09b6a7ad35118f12a6e4a7b93c8478b16465310b7f4271f3c394
MD5 84a1e3c785dbfb131c3c8383d5bc5f63
BLAKE2b-256 0d7537f000bcfc39e317c4eaddb1f5e65a607fa2bca067d5e8f6ad84dba9bcdb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for enki_py-0.5.5-py3-none-musllinux_1_2_armv7l.whl
Algorithm Hash digest
SHA256 16a28801a50a956b821d4c803db9d104ce6810554a39ea8c0fa39841643d6763
MD5 899ca72f93d678b46db46c2b6469b250
BLAKE2b-256 f159c903bbd7e32fff30fbccf11df45ba22ad878d62e7bb8d5823b76aa4a1ea9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for enki_py-0.5.5-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 31b8da023997e9c087acefbe7e78bd94588c0808a06c5d61a7603103e6dfbba1
MD5 4496f3e13473de5770103dd2a8b26fd6
BLAKE2b-256 239e3b515034cf0b8a42884ea28456a951a99bb9de03909a73dcb563e9cf0fdc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for enki_py-0.5.5-py3-none-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 913a2427a9e52e470918234f7ae952ec9ad088a8f8fced99e2f0354c901e4b72
MD5 36e5e16ada17a076fd22f02bb6654972
BLAKE2b-256 c0b4beb8a61cd4524b5b035a9ea18330162893d51346773675f6c073950b04df

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for enki_py-0.5.5-py3-none-manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 caa6ff30aaeebd276697b07d1c6cfb7d57bb3bb2c5e988f17ed17de786be7dee
MD5 2332123fb5a898b835a2ca29ca09b645
BLAKE2b-256 e61399cc417bd8cde6dcb8a7e44e78968d48b66ab22b973c887ffe9cf06025ba

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for enki_py-0.5.5-py3-none-manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 62a23d4f0b09f6a3e3ccabf74f73f9c55540abf2de889daff7921cc5c687b650
MD5 8bc13ff1e37c64da4f76af952e424017
BLAKE2b-256 8ba7cad57e006e2307c976df3d32c168814c8baca8fd6a94bd37cb8e4d16e4b5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for enki_py-0.5.5-py3-none-manylinux_2_28_i686.whl
Algorithm Hash digest
SHA256 f5ebf42cd0ca2fddf8edbd8a7f625533df49a6541a96bb18e8fd58eeda486e12
MD5 c77861f91e0e9cda0e4ac22e24af446f
BLAKE2b-256 fe457437aac3fb63e88151fb1cab2fd35b37c406329700eb53866f171d912b91

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for enki_py-0.5.5-py3-none-manylinux_2_28_armv7l.whl
Algorithm Hash digest
SHA256 6602b5e9b72dd9bdb46751a450c64bc19ffc4b0a5617c9dd6ed2bbe49d1b3154
MD5 5eb39236bbd995cb33b340f4f561f4a4
BLAKE2b-256 45a8ec6fbe4a8221d7bb96cb220f76cd1a9b05a8f9910855b9fab4caddf44f4e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for enki_py-0.5.5-py3-none-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 e45d5b67c6008822aea7bcfb64d0d1e490231834a61a41dc1b5832413669d8e1
MD5 ee12c804db1ab37fe7548269ab25d1b4
BLAKE2b-256 4f513ea5a33c911234f5b0be582e7f9d245d948b1dfd90bc03a4199b8c880a47

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for enki_py-0.5.5-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 958b7842814d734bd04dce12e66f950573d727c7a09b7d0364897ed6dc2087e9
MD5 0f60cfb00c24cbbc4f747bc333cc4771
BLAKE2b-256 b6bb81fd3bed9927518812912710a2d97737b737564889b1fa79ecd235aa2a36

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for enki_py-0.5.5-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 13e91ebd018cc40eb9c3c76d0c4097820ecf1fa527db7f8e9f3204ac7e69fdd4
MD5 6264864aefcb4c3ff7a5aad4328f0a50
BLAKE2b-256 4aa5a7c96b036cf4c84f06c2a62fd0ba47450d43addee0474f868711c6d95f57

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