Gigson Expert

/

September 18, 2026

Integrating Real-Time Port Data Into Agentic Logistics Planners

Learn how to connect real-time port data with agentic AI logistics planners to enable faster, more responsive freight decisions. This practical guide breaks down the architecture behind live port data ingestion, event normalization, and AI-powered replanning, with Python examples using FastAPI and HTTPX. It also explores common challenges such as API rate limits, legacy EDI systems, unreliable data, and human-in-the-loop decision-making.

Blog Image

Tadiwanashe Chibonda

Integrating Real-Time Port Data Into Agentic Logistics Planners

(Let's break it down, then build our own system)

By Tadiwanashe H N Chibonda, Zimbabwe 🇿🇼 

Let's take that title apart first, because on paper it reads like something only a supply-chain PhD would understand. It's not.

"Real-time port data" just means what's happening at the port right now. Has the ship shown up? Has a container cleared customs? Is the yard so full that another truck showing up would just be sitting in traffic for no reason?

"Agentic logistics planner" means an AI that doesn't just chat with you about logistics; it actually plans and acts. It decides things like "send truck A to grab container X at 3pm," and the important bit: it can change that plan on its own when something shifts, instead of everyone finding out three hours later that the plan was already dead on arrival.

"Integrating X into Y" is just the plumbing. It's building the pipe that carries live port updates to the AI making the calls, so it's working off what's true right now instead of what was true this morning.

So here's the plain-English version of the whole topic: how do you keep an AI delivery planner in sync with reality at the port, instead of it confidently planning around information that's already stale?

That gap, between what's actually happening and what the planning system thinks is happening, is where a suspicious number of logistics delays are born. Usually, because nobody knew about the problem. Because the person who knew wasn't the one holding the schedule.

What You'll Need Before We Start

No fancy hardware here, just a laptop and some patience for API docs. Here's the stack:

Software

  • Python 3.10 or newer
  • FastAPI (pip install fastapi uvicorn)
  • httpx for making API calls (pip install httpx)
  • Access to an LLM/agent API (OpenAI, Anthropic, or similar) with tool-calling support
  • A port data provider or sandbox API (some ports and freight platforms offer test/sandbox access; if you don't have one, you can mock the responses while learning the pattern)
  • A code editor (VS Code is fine)
  • A terminal you're not scared of

Hardware

  • Whatever you're reading this on right now is enough. This is not a machine-learning-training article; nobody's GPU needs to cry today.

Nice to have, not required

  • Basic familiarity with async/await in Python
  • A vague understanding of what a REST API is (if you can order food through an app, you already get the concept)

Now let's lock in.

Why This Is a Real Problem, Not Just a Buzzword Combo

Traditional freight planning software runs off a schedule that gets set once and then edited by hand whenever something changes. A dispatcher checks a port portal, maybe reads an email from a customs broker, maybe takes a phone call, then manually updates the plan. Every single one of those steps adds delay, and delay is exactly the thing you're trying to avoid.

Meanwhile, the port itself is throwing off information constantly. Container status updates, berth assignments, gate throughput, customs clearance events. Most of it never makes it to the planning system in a usable form. It just lives in a dashboard that somebody has to remember to check, assuming they even have time to.

An agentic planner flips the whole setup. Instead of a human fetching data and pushing updates by hand, the data pushes itself into the agent, and the agent replans immediately: reroute a truck, notify a customer, rebook a slot, all before a human would've even opened the dashboard tab.

Side by side, the difference looks like this:

 

Traditional Freight Planning

Agentic Logistics Planning

Data source

Manual checks: port portals, emails, phone calls

Live feeds: APIs, EDI, sensors

Update frequency

Whenever someone remembers to check

Continuous, as events happen

Response to disruption

Dispatcher notices, then manually replans

Agent detects and replans automatically

Typical response time

Hours, sometimes longer

Minutes, often seconds

Human's role

Executes every decision by hand

Reviews and approves flagged edge cases

The Architecture

Three moving parts here, and the shape will feel familiar if you've built any kind of live-data pipeline before.

  1. Ingest: pull data from the port's systems (APIs, EDI feeds, or sensors like gate cameras and crane telemetry)
  2. Normalize: clean it into one consistent format, because no two ports agree on how to structure anything
  3. Act: hand it to an agent that has real tools it can use: reroute, reschedule, notify

Step 1: Pulling in the Port Data

Fair warning, ports rarely hand you a clean REST API. A lot of this still runs on EDI (Electronic Data Interchange), a format that has been technically "working" since long before most of us were born and shows no interest in retiring. For this walkthrough, assume there's an API wrapper sitting in front of whatever the port actually gives you, because writing raw EDI parsers is a whole separate horror story.

import httpx

async def get_port_events(port_id: str, since_timestamp: str):
    """
    Pulls container, vessel, and gate events since the last check.
    """
    url = "https://api.port-data-provider.com/v1/events"
    params = {"port_id": port_id, "since": since_timestamp}

    async with httpx.AsyncClient() as client:
        response = await client.get(url, params=params)
        response.raise_for_status()
        return response.json()["events"]

This is a polling setup, which is the realistic starting point. Some port systems support webhooks or streaming, and that's genuinely better since you get pushed events instead of constantly asking "Anything new?” But most ports don't offer that yet, so build for polling first and treat push-based updates as a future upgrade.

Step 2: Normalizing the Mess

This is the unglamorous part that eats way more time than the AI bit ever will. One port calls it "vessel_eta." Another calls it "expected_arrival." A third buries it three fields deep inside an EDI segment that only makes sense to the person who designed it in 1998. Before any of this is useful to an agent, it all needs to look the same, no matter where it came from.

def normalize_event(raw_event: dict, source: str) -> dict:
    """
    Converts a port-specific event format into a common schema.
    """
    if source == "port_a":
        return {
            "type": raw_event.get("event_type"),
            "container_id": raw_event.get("container_ref"),
            "timestamp": raw_event.get("event_time"),
            "delay_minutes": raw_event.get("delay", 0),
        }
    elif source == "port_b":
        return {
            "type": raw_event.get("category"),
            "container_id": raw_event.get("cid"),
            "timestamp": raw_event.get("ts"),
            "delay_minutes": raw_event.get("delta_min", 0),
        }
    # add a branch per source you integrate with

If you're only working with one port right now, you can skip building this out fully. But design the schema like a second port is coming, because it always eventually shows up, usually right when you thought you were done.

Step 3: Feeding It to the Agent

Here's where this stops being "just a data pipeline" and starts earning the word agentic. The agent gets the normalized events as live context, plus a set of tools it's allowed to actually use: reroute a truck, notify a customer, rebook a slot.

async def run_planning_agent(current_plan: dict, new_events: list[dict]):
    """
    Passes live port events to the agent and lets it decide what,
    if anything, needs to change about the current delivery plan.
    """
    context = {
        "current_plan": current_plan,
        "new_events": new_events,
    }

    response = await agent_client.run(
        system_prompt=(
            "You are a logistics planning agent. Given the current delivery "
            "plan and new port events, decide if any deliveries need to be "
            "rerouted, rescheduled, or flagged for human review. Only act "
            "on events that materially affect the plan."
        ),
        input=context,
        tools=["reroute_truck", "reschedule_delivery", "notify_customer", "flag_for_human"],
    )

    return response.actions_taken

That one line in the prompt, "only act on events that materially affect the plan," matters more than it looks like it should. Skip it,  and you'll end up with an agent who, reroutes an entire truck because a container shifted ten feet within the same yard. Tune what counts as "material" based on what your actual planners would care about, not what technically counts as a change.

Access a Global Pool of Talented and Experienced Developers

Hire Skilled Professionals to Build Innovative Products

Start Hiring

What Breaks Once This Gets Real

A few things worth knowing before you build this for keeps, not just for a demo:

Bad data will trigger bad decisions. Port systems occasionally send wrong or duplicate events, because of computers. Before letting the agent act fully on autopilot, it's worth having it flag lower-confidence changes for a human to approve first, at least until you trust the pipeline enough to hand over the keys.

Polling frequency is a trade-off, not a setting you pick once and forget. Poll too often and you're burning through API calls and rate limits for basically nothing. Poll too rarely and you're back to the exact delay problem you built this to fix. Match the interval to how fast the port's data actually changes, not to how responsive you'd like it to feel.

Not every port even speaks the same language, literally. Some transmit data in local formats, different languages, or country-specific customs codes. If you're covering more than one region, your normalization layer needs to plan for that from day one, not get bolted on later in a panic.

FAQs

How do you handle API rate limits when polling multiple ports?

Stagger your polling instead of hitting every port's endpoint on the same schedule, and respect each provider's documented rate limit rather than assuming they're all the same. In practice, a simple per-source queue with backoff (retry with increasing delay after a 429 response) handles most of this. If you're polling more than a handful of ports, it's worth tracking rate-limit headroom per source so one aggressive port doesn't starve requests to the others.

What happens when an LLM tool call fails mid-execution?

Treat it like any other unreliable network call, because that's what it is. Wrap tool calls in retries with a capped attempt count, and have a defined fallback: if reroute_truck fails twice, the safest default is usually to flag the event for human review rather than silently dropping it or retrying indefinitely. Losing an update silently is worse than being slow.

How do you handle legacy EDI parsers in production?

Isolate them. EDI parsing logic tends to be brittle and format-specific, so keep it in its own module with heavy test coverage around the specific segments you actually use, rather than trying to build a general-purpose EDI parser. When a new port's format doesn't match what you've seen before, fail loudly and log the raw payload instead of guessing, so you can add a new mapping rather than silently misreading a field.

What if the agent's replan conflicts with a driver already en-route?

This is why the "material change" threshold matters. Give the agent visibility into which parts of the plan are already in motion (a truck that's left the yard, a driver who's confirmed a pickup) and treat those as higher-friction to change than parts of the plan that haven't started yet. A reroute for tomorrow's deliveries can happen automatically; a reroute for a truck five minutes from the gate should probably ping the driver and dispatcher before it's finalized.

The Actual Point of All This

Here's the twist: the AI was never the hard part. Models are already good enough at reasoning through "here's the situation, here's what changed, here's what should happen next." The real engineering work, the part that decides whether this whole thing holds up or quietly falls apart, is getting clean, current, consistently shaped data in front of the agent in the first place.

If you take one thing from this, an agentic system is only ever as good as what you feed it. The "agent" part is often the easy 20%. The pipeline dragging messy, real-world data into a shape it can actually use is the other 80%, and it's the part most tutorials skip because it's less fun to write about. Now you know better 

No items found.

Subscribe to our newsletter

The latest in talent hiring. In Your Inbox.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Hiring Insights. Delivered.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Read More

Request a call back

Lets connect you to qualified tech talents that deliver on your business objectives.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.