Cross-Team Information Graph Traversal | Generated by AI
Question: In enterprise environments, how do you effectively gather and connect information across Teams/company directories, GitHub, JIRA, and Confluence — especially when working on cross-team projects?
Answer:
This is fundamentally an information graph traversal problem. Enterprise knowledge is a DAG where nodes are people/tickets/docs/code and edges are implicit (mentioned in comments, linked pages, team memberships). The goal is to traverse it faster than everyone else.
Mental Model First
Person (Staff ID)
├── owns → JIRA tickets
├── wrote → Confluence pages
├── commits to → GitHub repos
├── belongs to → Teams/AD groups
└── referenced in → other people's tickets/pages
Your job cross-team is to build this graph locally as fast as possible.
Layer 1: Identity Resolution (Staff ID as Root)
Every enterprise uses an LDAP/Active Directory identity that maps to everything else. In banks especially, the Staff ID is the canonical key.
# AD/LDAP lookup (if you have ldapsearch access)
ldapsearch -x -H ldap://your-corp-ldap -b "dc=bank,dc=com" \
"(uid=zhiwei.li)" cn mail memberOf department manager
# Or via Python
pip install ldap3
from ldap3 import Server, Connection, ALL
s = Server('ldap://corp.bank.com', get_info=ALL)
c = Connection(s, 'CN=you,OU=Users,DC=bank,DC=com', 'password', auto_bind=True)
c.search('DC=bank,DC=com', '(sAMAccountName=lzw123)', attributes=['*'])
print(c.entries[0])
From Staff ID you can resolve: email, manager chain, team membership, AD groups (= repo/JIRA project access).
Layer 2: Confluence — Structured Knowledge Mining
Confluence has a decent REST API. The trick is knowing that Space → Pages → Labels → People is the traversal path.
import requests
from requests.auth import HTTPBasicAuth
BASE = "https://confluence.yourbank.com/rest/api"
AUTH = HTTPBasicAuth("you@bank.com", "your-api-token")
def search_confluence(query, limit=20):
"""CQL (Confluence Query Language) search"""
r = requests.get(f"{BASE}/content/search", auth=AUTH, params={
"cql": f'text ~ "{query}" AND type = page',
"limit": limit,
"expand": "metadata.labels,version,ancestors"
})
return r.json()["results"]
def get_page_by_staff_path(staff_id):
"""Directly hit staff profile pages"""
r = requests.get(f"{BASE}/content/search", auth=AUTH, params={
"cql": f'title = "{staff_id}" AND space.key = "STAFF"',
"expand": "body.storage,version"
})
return r.json()
def get_space_tree(space_key):
"""Enumerate all pages in a space"""
r = requests.get(f"{BASE}/space/{space_key}/content", auth=AUTH,
params={"expand": "page.children.page", "limit": 50})
return r.json()
# Find who owns what by creator/lastModified
def find_pages_by_person(username):
r = requests.get(f"{BASE}/content/search", auth=AUTH, params={
"cql": f'creator = "{username}" ORDER BY created DESC',
"limit": 50
})
return [(p["title"], p["_links"]["webui"]) for p in r.json()["results"]]
CQL patterns that actually matter cross-team:
# Find all pages referencing a ticket
text ~ "PROJ-1234"
# Find pages in a space updated in last 30 days
space.key = "ARCH" AND lastModified >= "2026-04-27"
# Find pages created by someone's team
creator in membersOf("team-payments") AND type = page
# Staff directory traversal
ancestor = "Staff Directory" AND title ~ "Platform"
Layer 3: JIRA — Graph of Work
JIRA’s JQL is powerful. Cross-team intelligence comes from traversing issue links, epics, and watchers.
import requests
JIRA_BASE = "https://jira.yourbank.com/rest/api/2"
AUTH = HTTPBasicAuth("you@bank.com", "token")
def jql(query, fields="summary,assignee,reporter,status,labels,issuelinks,comment"):
r = requests.get(f"{JIRA_BASE}/search", auth=AUTH, params={
"jql": query,
"fields": fields,
"maxResults": 100
})
return r.json()["issues"]
# Cross-team: find all epics a person is involved in
issues = jql('assignee = "zhiwei.li" OR reporter = "zhiwei.li" OR watcher = "zhiwei.li"')
# Find who is touching the same component as you
issues = jql('component = "PaymentGateway" AND updated >= -30d ORDER BY updated DESC')
# Find all blockers across projects
issues = jql('issueType = "Story" AND "Epic Link" = "PLAT-100" AND project in (PLAT, RISK, DATA)')
# Traverse issue links programmatically
def get_linked_issues(issue_key):
r = requests.get(f"{JIRA_BASE}/issue/{issue_key}", auth=AUTH,
params={"fields": "issuelinks,subtasks,parent"})
data = r.json()["fields"]
links = []
for link in data.get("issuelinks", []):
linked = link.get("inwardIssue") or link.get("outwardIssue")
if linked:
links.append((link.get("type", {}).get("name"), linked["key"], linked["fields"]["summary"]))
return links
JQL patterns for cross-team:
# Everything touching your team's components in any project
component in ("Auth", "Gateway") AND project != MYTEAM
# Find people who reviewed/commented on related tickets
issue in watchedIssues("relevant.person@bank.com")
# Sprint cross-team view
sprint in openSprints() AND project in (PLAT, DATA, RISK, INFRA)
# Find all tickets a staff member ever touched
(assignee = "staff123" OR reporter = "staff123") ORDER BY updated DESC
Layer 4: Enterprise GitHub
GitHub Enterprise has a great API. Key insight: org teams map to AD groups, which maps back to your LDAP graph.
import requests
GHE = "https://github.yourbank.com/api/v3"
HEADERS = {"Authorization": "token ghp_yourtoken", "Accept": "application/vnd.github.v3+json"}
def get_org_teams(org):
r = requests.get(f"{GHE}/orgs/{org}/teams", headers=HEADERS)
return [(t["name"], t["slug"]) for t in r.json()]
def get_team_members(org, team_slug):
r = requests.get(f"{GHE}/orgs/{org}/teams/{team_slug}/members", headers=HEADERS)
return [m["login"] for m in r.json()]
def find_repos_by_topic(org, topic):
r = requests.get(f"{GHE}/search/repositories",
headers=HEADERS,
params={"q": f"org:{org} topic:{topic}"})
return [(repo["name"], repo["html_url"]) for repo in r.json()["items"]]
def get_cross_team_contributors(org, repo):
"""Who outside your team commits here?"""
r = requests.get(f"{GHE}/repos/{org}/{repo}/contributors", headers=HEADERS)
return [(c["login"], c["contributions"]) for c in r.json()]
def code_search(org, query):
"""Find all usages of an API/class across org"""
r = requests.get(f"{GHE}/search/code",
headers=HEADERS,
params={"q": f"org:{org} {query}"})
return [(i["repository"]["name"], i["path"], i["html_url"]) for i in r.json()["items"]]
The killer use case: code_search across org to find who else calls your API, then cross-reference their GitHub logins to JIRA assignees to find the right people to talk to.
Layer 5: Teams / MS Graph API
If the company uses Microsoft 365 (common in banks), MS Graph is your people graph.
import requests
# Auth: get token via client_credentials or device_flow
TOKEN = "your_ms_graph_token"
GRAPH = "https://graph.microsoft.com/v1.0"
H = {"Authorization": f"Bearer {TOKEN}"}
def find_person(name_or_email):
r = requests.get(f"{GRAPH}/users", headers=H,
params={"$filter": f"startswith(displayName,'{name_or_email}')",
"$select": "displayName,mail,jobTitle,department,manager"})
return r.json()["value"]
def get_manager_chain(user_id, depth=3):
"""Walk up the org chart"""
chain = []
current = user_id
for _ in range(depth):
r = requests.get(f"{GRAPH}/users/{current}/manager", headers=H,
params={"$select": "displayName,mail,id"})
if r.status_code != 200:
break
mgr = r.json()
chain.append(mgr["displayName"])
current = mgr["id"]
return chain
def get_team_channels(team_id):
r = requests.get(f"{GRAPH}/teams/{team_id}/channels", headers=H)
return [(c["displayName"], c["id"]) for c in r.json()["value"]]
def get_person_groups(user_id):
"""All AD/Teams groups this person belongs to"""
r = requests.post(f"{GRAPH}/users/{user_id}/getMemberGroups", headers=H,
json={"securityEnabledOnly": False})
return r.json()["value"] # group IDs → cross-ref with GitHub teams
Layer 6: Build Your Own Cross-System Index
The real leverage is connecting these into a local index. Here’s a minimal version:
# enterprise_graph.py — local cross-system knowledge graph
import json, sqlite3
conn = sqlite3.connect("enterprise.db")
conn.executescript("""
CREATE TABLE IF NOT EXISTS people (
staff_id TEXT PRIMARY KEY,
email TEXT, display_name TEXT,
github_login TEXT, jira_username TEXT,
team TEXT, manager_chain TEXT
);
CREATE TABLE IF NOT EXISTS artifacts (
id TEXT PRIMARY KEY,
type TEXT, -- 'confluence_page' | 'jira_ticket' | 'github_repo'
title TEXT, url TEXT, owner_staff_id TEXT,
tags TEXT, updated TEXT
);
CREATE TABLE IF NOT EXISTS edges (
from_id TEXT, to_id TEXT, relation TEXT
-- 'mentions' | 'assigned_to' | 'blocks' | 'contributes_to'
);
""")
def ingest_person(staff_id, email, github, jira, team, manager_chain):
conn.execute("""INSERT OR REPLACE INTO people VALUES (?,?,?,?,?,?,?)""",
(staff_id, email, None, github, jira, team, json.dumps(manager_chain)))
conn.commit()
def find_person_artifacts(staff_id):
return conn.execute("""
SELECT type, title, url FROM artifacts WHERE owner_staff_id = ?
""", (staff_id,)).fetchall()
def find_connected_people(staff_id, hops=2):
"""BFS over edges to find related people"""
visited = {staff_id}
frontier = [staff_id]
for _ in range(hops):
next_frontier = []
for node in frontier:
neighbors = conn.execute("""
SELECT DISTINCT to_id FROM edges WHERE from_id = ?
UNION SELECT DISTINCT from_id FROM edges WHERE to_id = ?
""", (node, node)).fetchall()
for (n,) in neighbors:
if n not in visited:
visited.add(n)
next_frontier.append(n)
frontier = next_frontier
return visited - {staff_id}
Tactical Playbook for Cross-Team Work
| Goal | Command |
|---|---|
| Who owns component X? | JQL: component = X ORDER BY updated DESC → look at assignees |
| Find the Confluence runbook | CQL: text ~ "X" AND ancestor = "Runbooks" |
| Who else uses my API? | GitHub code search: org:bank "MyServiceClient" |
| Who’s the right person in team Y? | LDAP → AD group → GitHub team members → JIRA watchers |
| What did person X build? | Confluence: creator = X, GitHub: /users/X/repos, JIRA: assignee = X |
| Find undocumented dependencies | GitHub: cross-repo import search → cross-ref JIRA component owners |
Automate It With a CLI Agent
Since you already build CLI agents (ww, iclaw, zz), wire this into one:
# Query person across all systems
ent-search person "zhiwei.li"
# → AD profile, GitHub repos, JIRA tickets, Confluence pages
# Find who to talk to about a topic
ent-search topic "payment gateway rate limiting"
# → Confluence pages + JIRA tickets + GitHub code + people involved
# Map a cross-team epic
ent-search epic PLAT-100
# → all linked tickets, all assignees, all Confluence pages mentioning it
This is genuinely the highest-leverage tool you can build at a bank — engineers who can navigate the information graph faster have outsized impact, especially in cross-team projects where context is the bottleneck, not code.