All skills

Guide for writing Python code with AlgoKit Utils (`algokit-utils`). Use this skill whenever the user is building on Algorand with Python — client setup, account management, payments, ASA operations, atomic transaction groups, smart contract deployment and interaction (AppFactory, AppClient, ARC-56/ARC-32 specs), raw app calls, TEAL compilation, key registration, network management, error handling, and the low-level crypto primitives in `algokit_crypto` (Ed25519 keygen/signing/verification, Peikert xHD BIP44 wallets, wrapped-secret patterns) and `algokit_common` (`sha512_256`). Trigger on imports from `algokit_utils` or `algokit_crypto`, references to `AlgorandClient`, `AppFactory`, `AppClient`, `AlgoAmount`, `ed25519_generator`, `peikert_hd_wallet_generator`, `sha512_256`, `WrappedEd25519Seed`, or `RawEd25519Signer`, or any Python code that builds on Algorand.

Use this Skill: https://skilld.dev/gh/algorand-devrel/algorand-agent-skills/algokit-utils-py

This session only. Nothing lands on disk.

referencestransaction-composition.md

≈1.8k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Transaction composition (atomic groups)

All snippets in this section assume an AlgorandClient named algorand — see Client initialization for setup.

Create a transaction group

Start composing an atomic group of transactions.

from algokit_utils import AlgorandClient

algorand = AlgorandClient.default_localnet()

composer = algorand.new_group()

What just happened: algorand.new_group() creates a new TransactionComposer instance. Every transaction you add to this composer will be submitted as a single atomic group — they all succeed together or all fail together.

Add multiple transactions to a group

Combine a payment and an asset transfer into one atomic group.

from algokit_utils import PaymentParams, AssetTransferParams
from algokit_utils.models.amount import AlgoAmount

result = (
    algorand.new_group()
    .add_payment(
        PaymentParams(sender=alice.addr, receiver=bob.addr, amount=AlgoAmount(algo=1))
    )
    .add_asset_transfer(
        AssetTransferParams(sender=alice.addr, receiver=bob.addr, asset_id=12345, amount=100)
    )
    .send()
)

print(f"Group ID: {result.group_id}")
print(f"Transaction IDs: {result.tx_ids}")

What just happened: Each add_payment() and add_asset_transfer() call returns the composer for fluent chaining. When you call .send(), both transactions are grouped, signed, and submitted atomically — the payment and asset transfer either both confirm or both fail.

Multi-signer group

Different transactions in a group can have different signers.

from algokit_utils import PaymentParams
from algokit_utils.models.amount import AlgoAmount

alice = algorand.account.random()
bob = algorand.account.random()

dispenser = algorand.account.localnet_dispenser()
algorand.account.ensure_funded(alice.addr, dispenser.addr, AlgoAmount(algo=10))
algorand.account.ensure_funded(bob.addr, dispenser.addr, AlgoAmount(algo=10))

result = (
    algorand.new_group()
    .add_payment(
        PaymentParams(sender=alice.addr, receiver=bob.addr, amount=AlgoAmount(algo=1))
    )
    .add_payment(
        PaymentParams(sender=bob.addr, receiver=alice.addr, amount=AlgoAmount(algo=2))
    )
    .send()
)

What just happened: Each PaymentParams specifies a different sender. The TransactionComposer resolves each sender's signer via the AccountManager — accounts created with account.random() are auto-registered, so no manual signer setup is needed.

Atomic swap

Exchange assets between two parties — both transfers succeed or both fail.

from algokit_utils import PaymentParams, AssetTransferParams
from algokit_utils.models.amount import AlgoAmount

# Atomic swap: Alice sends 100 Gold to Bob, Bob sends 5 ALGO to Alice
result = (
    algorand.new_group()
    .add_asset_transfer(
        AssetTransferParams(sender=alice.addr, receiver=bob.addr, asset_id=gold_id, amount=100)
    )
    .add_payment(
        PaymentParams(sender=bob.addr, receiver=alice.addr, amount=AlgoAmount(algo=5))
    )
    .send()
)

What just happened: The asset transfer and payment are grouped into a single atomic transaction. The Algorand protocol guarantees that either both execute or neither does — if Bob doesn't have enough ALGO, Alice's asset transfer is also rejected, eliminating counterparty risk.

Build and send an atomic group

Build the group to inspect transactions before sending.

from algokit_utils import PaymentParams
from algokit_utils.models.amount import AlgoAmount

composer = (
    algorand.new_group()
    .add_payment(
        PaymentParams(sender=sender.addr, receiver=receiver.addr, amount=AlgoAmount(algo=1))
    )
    .add_payment(
        PaymentParams(sender=sender.addr, receiver=receiver.addr, amount=AlgoAmount(algo=2))
    )
)

built = composer.build()
print(f"Group contains {len(built.transactions)} transactions")

result = composer.send()
print(f"Confirmed in round: {result.confirmations[0].confirmed_round}")

What just happened: Calling .build() composes and returns the transaction group with signers attached, letting you inspect the transactions before committing. A subsequent .send() signs and submits the already-built group.

Simulate a transaction group before sending

Dry-run a group to check for errors without spending Algo.

from algokit_utils import PaymentParams
from algokit_utils.models.amount import AlgoAmount

composer = algorand.new_group().add_payment(
    PaymentParams(sender=sender.addr, receiver=receiver.addr, amount=AlgoAmount(algo=5))
)

sim_result = composer.simulate(skip_signatures=True)

assert sim_result.simulate_response is not None
print(f"Would succeed: {len(sim_result.confirmations) > 0}")
print(f"Simulated round: {sim_result.simulate_response.last_round}")

What just happened: .simulate(skip_signatures=True) sends the group to the node's simulate endpoint, which evaluates it without real signatures or on-chain effects. The result includes a simulate_response with detailed execution info. This is useful for validating logic, checking opcode budgets, and estimating fees before sending real transactions.

Set fees on grouped transactions

Control fees at the per-transaction level within a group.

from algokit_utils import PaymentParams
from algokit_utils.models.amount import AlgoAmount

result = (
    algorand.new_group()
    .add_payment(
        PaymentParams(
            sender=sender.addr,
            receiver=receiver.addr,
            amount=AlgoAmount(algo=1),
            extra_fee=AlgoAmount(micro_algo=1000),  # covers an inner transaction
        )
    )
    .add_payment(
        PaymentParams(
            sender=sender.addr,
            receiver=receiver.addr,
            amount=AlgoAmount(algo=2),
            max_fee=AlgoAmount(micro_algo=3000),  # cap to prevent overspending
        )
    )
    .send()
)

What just happened: Fee control is set per transaction, not per group. extra_fee adds to the network-suggested fee (useful when a transaction triggers inner transactions that need fee coverage), and max_fee throws an error if the calculated fee exceeds the cap — protecting you from overspending during congestion.

Clone a composer for reuse

Duplicate a composer so you can send the same group template multiple times.

from algokit_utils import PaymentParams
from algokit_utils.models.amount import AlgoAmount

template = algorand.new_group().add_payment(
    PaymentParams(sender=sender.addr, receiver=receiver.addr, amount=AlgoAmount(algo=1))
)

copy = template.clone()

result = copy.send()
print(f"Sent from clone: {result.tx_ids[0]}")

What just happened: .clone() creates a shallow copy of the composer, including all queued transactions. The original and the clone are fully independent — you can modify or send one without affecting the other. This is handy for reusable transaction templates.

Source: SKILL.md on GitHub

1 warning1mo3 checks · Risk SAFE
  • Gen Agent Trust Hub1mo

    The skill is a technical reference guide for the Algorand Python SDK (AlgoKit Utils). It promotes secure coding practices, including environment-based secret management and memory-safe cryptographic patterns for handling private keys. No malicious patterns or security risks were identified.

  • Socket1mo

    No alerts

  • Snyk1mo

    Risk: MEDIUM · 2 issues

Signed by skilld at 4235fb8. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 3 weeks ago.

Activeupdated 6 months ago

README badge

README badge for algorand-devrel/algorand-agent-skills/algokit-utils-py