Skip to main content

DISCLAIMER: The following documentation is for gama-client 2.0.0 and above. This is a major release containing breaking changes compared to the 1.x versions.

Gama client

Gama-client is a Python module designed to facilitate interactions with the headless mode of the modeling and simulation platform known as GAMA. It handles the connection to gama-server via WebSockets and sends properly formatted JSON requests.

While the GAMA server operates asynchronously, gama-client provides multiple paradigms to interact with it, ranging from a simple synchronous (blocking) API to a fully asynchronous API for advanced parallelism.

Installation

In your Python environment, install the gama-client package with the following command:

pip install gama-client

You can verify the installation by opening a Python console and running:

from gama_client.sync_client import GamaSyncClient

If no errors appear, the installation was successful.

Usage

Requirements

To use gama-client, you must have an instance of GAMA Headless Server running (e.g., on localhost:6868).


1. Quick Start: Synchronous Mode (Default & Recommended)

The GamaSyncClient is the default and simplest way to interact with GAMA. It provides synchronous (blocking) methods for all commands, meaning your Python script will wait for GAMA to finish executing the command before proceeding to the next line. This is ideal for basic model manipulation and sequential scripts.

Example:

import asyncio
from gama_client.sync_client import GamaSyncClient
from gama_client.message_types import MessageTypes


async def main():
    # 1. Initialize and connect the client
    client = GamaSyncClient("localhost", 6868)
    client.connect()

    # 2. Load a model
    print("Loading model...")
    response = client.load("path/to/your/model.gaml", "experiment_name")
    
    # Check if successful and get the experiment ID
    if response["type"] == MessageTypes.CommandExecutedSuccessfully.value:
        exp_id = response["content"]
        print(f"Model loaded. Experiment ID: {exp_id}")
    else:
        print("Failed to load model:", response)
        return

    # 3. Run the simulation for 100 steps
    print("Running 100 steps...")
    client.step(exp_id, nb_step=100)

    # 4. Evaluate an expression (e.g., get the current cycle)
    cycle_response = client.expression(exp_id, "cycle")
    print("Current cycle is:", cycle_response["content"])

    # 5. Change a variable in your simulation
    var_response = client.expression(exp_id, "my_variable <- 42;")
    if var_response["type"] == MessageTypes.CommandExecutedSuccessfully.value:
        print("Variable changed successfully")
    else:
        print("Failed to change variable: " + var_response["content"])

    # 6. Clean up
    client.stop(exp_id)
    client.close_connection()

if __name__ == "__main__":
    asyncio.run(main())

2. Advanced: Asynchronous Execution

Using Awaitable methods

If your Python application is heavily based on asyncio and you do not want to block the main event loop while waiting for GAMA's responses, you can use the _awaitable suffix on any command from the GamaSyncClient (e.g., client.load_awaitable(...)).

These methods return a coroutine that you must await. The major advantage is that you don't need to manually link the request to the response in a global handler (like in pure async mode) — the await returns the exact answer for that specific command. Meanwhile, your Python program can do other things in the background while GAMA is computing.

import asyncio

async def do_background_work():
    print("Doing work while GAMA is loading...")
    await asyncio.sleep(1)

async def main():
    client = GamaSyncClient("localhost", 6868)
    client.connect()

    # Launch a GAMA command and a background task concurrently
    gama_task = asyncio.create_task(client.load_awaitable("model.gaml", "exp"))
    other_task = asyncio.create_task(do_background_work())

    # Wait for both
    response, _ = await asyncio.gather(gama_task, other_task)
    print("GAMA answered! Experiment ID:", response["content"])

Pure Asynchronous (Fire-and-forget)

If you want to manage many simulations simultaneously or send commands without pausing for responses, you should use the pure asynchronous paradigm.

Every command is available with an _async suffix (e.g., load_async(), step_async()). When called, the command is dispatched immediately, and your script moves to the next line. To catch the responses, simulation outputs, or errors, you must provide a message_handler function.

Did you know? You can mix modes! The GamaSyncClient inherits all _async methods. This means you can comfortably mix blocking synchronous commands (like load to set up a model sequentially) with pure asynchronous commands (like step_async to run multiple simulations in parallel) using the same client. To do this, simply provide your handlers during the initialization of the GamaSyncClient as shown below.

import asyncio
from gama_client.sync_client import GamaSyncClient

async def async_command_answer_handler(message):
    print("Answer to an _async command received:", message)

async def gama_server_message_handler(message):
    print("General message (outputs, errors) received:", message)

async def main():
    client = GamaSyncClient("localhost", 6868, async_command_answer_handler, gama_server_message_handler)
    client.connect()

    # Synchronous loading (easy and safe)
    res = client.load("path/to/model.gaml", "exp")
    
    # Asynchronous step (fire and forget, answer goes to async_command_answer_handler)
    await client.step_async(res["content"], nb_step=100)

    # Keep program alive to receive the asynchronous messages
    await asyncio.sleep(5)
    client.close_connection()

(Note: If you only plan to use pure asynchronous commands and want absolute maximum performance, you can use the GamaAsyncClient class directly. It strips away the tracking overhead required by the GamaSyncClient.)

Retrieving an _async command's answer

Because all asynchronous responses go to the global message_handler, tracking which answer corresponds to which command can be difficult.

To solve this, every _async command accepts an additional_data dictionary parameter. Any data you pass here will be echoed back by GAMA in the response. You can use this to pass unique IDs (like uuid or a counter) to route answers correctly in your handler.


Timeout Management

By default, synchronous and awaitable commands have no timeout. To prevent your script from hanging indefinitely if the GAMA server encounters an error or takes too long, you can set a one in two different ways:

  • GamaSyncClient Initialization: You can define a default_timeout (in seconds) when instantiating the client. This will apply to all the synchronous and awaitable commands run by this client.
  • Per-Command Timeout: Every synchronous and awaitable method accepts a timeout parameter to override the default for that specific call.
# Timeout after 60 seconds
response = client.load("model.gaml", "exp", timeout=60.0) 

If the timeout is reached, an asyncio.TimeoutError is raised.


Breaking Changes in 2.0.0

Version 2.0.0 is a major overhaul of the API aimed at standardizing how commands are sent and awaited, and making the synchronous mode more robust.

Major API Changes:

  1. GamaBaseClient renamed to GamaAsyncClient: The class providing the pure asynchronous (fire-and-forget) implementation has been renamed for clarity.
  2. Method suffixing in GamaAsyncClient: All command methods in the async client have been suffixed with _async (e.g., load() is now load_async(), step() is step_async()).
  3. Synchronous methods are now the default names: In GamaSyncClient, the clean method names (e.g., load(), step()) now refer to the fully synchronous, blocking versions. (Previously, these names were used for the async versions inherited from the base client).
  4. _awaitable methods introduced: GamaSyncClient now provides _awaitable versions for all commands (e.g., load_awaitable()) for users who want to await the server's response in an async loop without blocking the entire thread.

New Features & Fixes:

  • Timeouts: All synchronous and awaitable commands now support a timeout parameter (and the client accepts a default_timeout upon initialization) to prevent the program from hanging indefinitely if GAMA Server fails to respond. This resolves major hanging issues encountered in previous versions.
  • Full Parity: Missing commands like ask, upload, download, and exit have been fully implemented across all three modes (async, awaitable, sync).
  • Unified Test Suite: Complete refactoring of the test suites, ensuring identical coverage and behavior validation for all three API modes.

Example Code

Working examples can be found in the examples directory of the repository. You simply need to adjust the variables (server_url, gaml_file_path, etc.) to match your local setup.

  • The sync_examples directory focuses on the recommended GamaSyncClient.
  • The async_examples directory demonstrates the pure GamaAsyncClient usage.

To generate a new release (for contributors only)

Using github action

There is a github action: .github/workflows/python-publish.yml that automatically builds and uploads the new files to pypi.

Manually the new files to pypi

For reference: this documentation is based on this tutorial. Please check it out for more details about tools to install and/or context.

  • increment the version number in pyproject.toml
  • commit your changes to github
  • make sure you installed the required tools by running
python -m pip install --upgrade build twine
  • in the project's folder, to build the library, run
python -m build
  • then, to upload the generated files, run
python -m twine upload --repository pypi dist/*
  • on github, go to releases
  • click on create a new release
  • in tag, create a new tag with the new release number
  • add a description of the changes
  • in binaries, upload the two .whl and .tar.gz files generated by the build command
  • click on publish release

Metadata

Release files for gama-client 2.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gama-client 2.0.1
File Size Uploaded
gama_client-2.0.1.tar.gz 14.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for gama-client 2.0.1
File Interpreter ABI Platform
gama_client-2.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 31.9 kB

Release files / gama_client-2.0.1.tar.gz

Download URL gama_client-2.0.1.tar.gz
Size 14.7 kB
Tags Source
SHA-256 checksum
How to use checksums
1fd1103807d19c8161629e4f8bd7923f3439ca07f83e2636ceb8012eb6b52883
BLAKE2b-256 checksum
How to use checksums
3ac4a83b706184edc1cdc4ae798bf29f41ef4a5e05288df4a4516e922f887303
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 May 27, 2026.

Transparency log

Release files / gama_client-2.0.1-py3-none-any.whl

Download URL gama_client-2.0.1-py3-none-any.whl
Size 17.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
02993736a6e9f52a763ac9461c0565108687db04186da5e9f84807a92ce915cf
BLAKE2b-256 checksum
How to use checksums
4188a1ab88f95dfa8c83aef97c27b49a8437c129a61cc0d7d940c22bd093e424
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 May 27, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

2.0.1 This release

2 release files

2.0.0

2 release files

1.2.4

2 release files

1.2.3

2 release files

1.2.2

2 release files

1.2.1

2 release files

1.2.0

2 release files

1.1.5

2 release files

1.1.4

2 release files

1.1.3

2 release files

1.1.2

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.3

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page